洛谷 [P2349] 金字塔
洛谷【P2349】金字塔
有一盗墓者潜入一金字塔盗宝。当她(难道是Lara Croft ?)打开一个宝箱的时候,突然冒出一阵烟(潘多拉的盒子?),她迅速意识到形势不妙,三十六计走为上计……由于她盗得了金字塔的地图,所以她希望能找出最佳逃跑路线。地图上标有N个室,她现在就在1室,金字塔的出口在N室。她知道一个秘密:那阵烟会让她在直接连接某两个室之间的通道内的行走速度减半。她希望找出一条逃跑路线,使得在最坏的情况下所用的时间最少。
输入输出格式
输入格式:
输入文件的第一行有两个正整数N(3≤N≤100)和M(3≤M≤2000);下面有M行,每行有三个数正整数U、V、W,表示直接从U室跑到V室(V室跑到U室)需要W(3≤W≤255)秒。
输出格式:
输出所求的最少时间(单位为秒)。本题需要统计每条到达终点的路径,并在其中求出最大的一条边
解题
最后统计答案的时候只需要当前路径的长度+其中最大的一条边
公式:ans=max{dis[x]+maxedge[x]}
但我要介绍一个新的算法,此题可用A*来做
A*的大体思路是这样的:
我们构造需要一个估价函数来寻找最优解
初始化出每个结点的预估值(这道题预估值为每个结点到终点的最短路径长度,可用反向最短路求)
每次扩展最优的结点(因此可以用堆来维护,我用的是STL优先队列)
每次扩展每个结点的实际值(这到题的实际值为当前结点到起点的路径长度)
最后每次到达终点时我们统计答案
运行速度还是可以,相比二分+dijkstra快很多
看到别人还可以之用一次spfa就可以跑实在是dalao先%%%
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| #include <cstdio> #include <iostream> #include <cstdlib> #include <cstring> #include <queue>
using namespace std; const int maxn=100+5; const int maxm=2000+5; struct e{ int to,nxt,w; }; e edge[maxm<<1]; int head[maxn],edge_len,n,m; int dis[maxn],ans=0x3f3f3f3f; struct nd{ int node,len,maxx; bool operator <(const nd &a)const{ return len+dis[node]>a.len+dis[a.node]; } };
inline void edge_add(int u,int v,int w) { edge[edge_len].to=v; edge[edge_len].w=w; edge[edge_len].nxt=head[u]; head[u]=edge_len++; }
inline int inint() { int x=0;char c=getchar();bool flag=false; for(;!isdigit(c);c=getchar()) if(c=='-') flag=true; for(;isdigit(c);x=x*10+c-'0',c=getchar()); return flag?-x:x; }
bool inq[maxn]; void spfa(int s) { queue<int> q; q.push(s); inq[s]=true,dis[s]=0; while(!q.empty()) { int now=q.front();q.pop(); inq[now]=false; for(int i=head[now],v=edge[i].to;~i;i=edge[i].nxt,v=edge[i].to) { if(dis[v]>dis[now]+edge[i].w) { dis[v]=dis[now]+edge[i].w; if(!inq[v]) inq[v]=true,q.push(v); } } } }
void Astar(int s,int t) { priority_queue<nd> q; nd temp; temp.len=0,temp.node=s,temp.maxx=0; q.push(temp); while(!q.empty()) { nd now=q.top();q.pop(); if(now.node==t) { ans=min(ans,now.len+now.maxx); continue; } for(int i=head[now.node],v=edge[i].to;~i;i=edge[i].nxt,v=edge[i].to) { temp=now; temp.len+=edge[i].w; temp.node=v; temp.maxx=max(temp.maxx,edge[i].w); if(temp.len+temp.maxx+dis[v]>ans) continue; q.push(temp); } } }
int main(int argc, char **argv) { memset(head,-1,sizeof(head)); memset(dis,0x3f3f3f3f,sizeof(dis)); n=inint(),m=inint(); for(int i=1;i<=m;i++) { int a=inint(),b=inint(),c=inint(); edge_add(a,b,c),edge_add(b,a,c); } spfa(n); Astar(1,n); printf("%d\n",ans); return 0; }
|