poj 2387 Til the Cows Come Home spfa基础题,入门,我的第一个

 终于想到spfa的好处了,首先要比dij快啊!!dij是所有点汤一遍,而spfa用链表有方向的,还有dij遇见负权边就完了
dijkstra 不能有负权边,否则结果是错的,你想想,假如无向图有1,2,3个点,w(1,2)=1,w(1,3)=2,w(2,3)=-2. 按dij算法求求看。
 
实现方法:建立一个队列,初始时队列里只有起始点,在建立一个表格记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为0)。然后执行松弛操作,用队列里有的点去刷新起始点到所有点的最短路,如果刷新成功且被刷新点不在队列中则把该点加入到队列最后。重复执行直到队列为空
判断有无负环:如果某个点进入队列的次数超过N次则存在负环

存在负权回路的图是不能求两点间最短路的,因为只要在负权回路上不断兜圈子,所得的最短路长度可以任意小。

#include<iostream> using namespace std; #include<algorithm> #include<queue> #define N 10005 #define inf 0x7FFFFF struct node { int u; int c; int next; }e[N]; int d[N],p[N]; bool vis[N]; int spfa(int s) { d[s]=0; // vis[s]=true; queue<int>q; q.push(s); while(!q.empty()) { int t=q.front(); q.pop(); vis[t]=false; for(int j=p[t];j!=-1;j=e[j].next)//这是想大于有方向的爬树,比dij快多了 { int w=e[j].c; int temp=e[j].u; if(w+d[t]<d[temp]) { d[temp]=w+d[t]; if(!vis[temp]) //防止出现环,也就是进队列重复了 { vis[temp]=true; q.push(temp); } } } } } int main() { int t,n,a,b,c; while(cin>>t>>n) { memset(p,-1,sizeof(p)); memset(vis,false,sizeof(vis)); fill(d,d+N,inf); int temp=0; while(t--) { scanf("%d%d%d",&a,&b,&c);//双向链表 e[temp].u=b; e[temp].c=c; e[temp].next=p[a]; p[a]=temp; temp++; e[temp].u=a; e[temp].c=c; e[temp].next=p[b]; p[b]=temp; temp++; } spfa(1); cout<<d[n]<<endl; } return 0; }

你可能感兴趣的:(poj 2387 Til the Cows Come Home spfa基础题,入门,我的第一个)