[Usaco2009 Oct]Heat Wave 热浪 最短路之spfa
本人水平有限,题解不到为处,请多多谅解
本蒟蒻谢谢大家观看
关于spfa,它死了。
但是spfa还是有优点的:
SPFA算法是西南交通大学段凡丁于1994年发表的。
SPFA 也是竞赛中最常见的算法之一,不仅仅用来解决带负权的单源最短路
而且是求解差分约束问题的专用算法,也常用它和最大流合作解决最小费问题
题目:传送门
题目大意:
spfa模板,用循环队列优化
直接套模板即可。
code:
1 #include<bits/stdc++.h> 2 #define inf 0x3f3f3f3f 3 #pragma GCC optimize(3) 4 const int N=1e5+10; 5 using namespace std; 6 int T,C,s,e; 7 int ver[N*2],nxt[N*2],head[N],edge[N*2]; 8 int dis[N]; 9 bool vis[N]; 10 int tot; 11 queue<int>q;//循环队列,可重复进出 12 inline int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 15 while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 16 return x*f; 17 } 18 inline void write(int x) 19 { 20 if(x<0)x=-x,putchar('-'); 21 if(x>9)write(x/10); 22 putchar(x%10+'0'); 23 } 24 void add(int x,int y,int z){ 25 ++tot; 26 ver[tot]=y; 27 edge[tot]=z; 28 nxt[tot]=head[x]; 29 head[x]=tot; 30 } 31 int spfa(int b){ 32 for(int i=1;i<=T;i++){ 33 dis[i]=inf;//初始距离最大 34 vis[i]=0;//所有点都没有进队列 35 } 36 dis[b]=0;//是以b为根,所以初始b的距离为0 37 vis[b]=1;//初始b进队列 38 q.push(b); 39 while(q.size()){//只有当队列不为空时才能继续访问 40 int x=q.front();//取出队首 41 q.pop(); 42 vis[x]=0;//x出队列,此时x已不在队中 43 for(int i=head[x];i;i=nxt[i]){ 44 int y=ver[i],z=edge[i]; 45 if(dis[y]>dis[x]+z){ 46 dis[y]=dis[x]+z;//更新以b为根到y的距离的最小值 47 if(!vis[y]){//若y还没有进队列 48 q.push(y);//让y进队列 49 vis[y]=true;//此时y已入队 50 } 51 } 52 } 53 } 54 } 55 int main() 56 { 57 T=read(),C=read(); 58 s=read(),e=read(); 59 for(int i=1,x,y,z;i<=C;i++){ 60 x=read(),y=read(),z=read(); 61 add(x,y,z); 62 add(y,x,z); 63 } 64 spfa(s); 65 printf("%d\n",dis[e]); 66 return 0; 67 } 68 /* 69 7 11 5 4 70 2 4 2 71 1 4 3 72 7 2 2 73 3 4 3 74 5 7 5 75 7 3 3 76 6 1 1 77 6 3 4 78 2 4 3 79 5 6 3 80 7 2 1 81 */
注意:由于一个节点可能入队,出队多次,在一些特殊图上,可能出题人会卡spfa,将原本的O(km)退化成O(nm),必须慎用