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

来源:互联网 发布:怎么建立数据透视表 编辑:程序博客网 时间:2024/05/16 14:10
 终于想到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 0x7FFFFFstruct 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;}