循环的提前跳出:在实际操作中,贝尔曼-福特算法经常会在未达到V-1次前就出解,V-1其实是最大值。于是可以在循环中设置判定,在某次循环不再进行松弛时,直接退出循环,进行负权环判定。 具体做法是用一个队列保存待松弛的点,然后对于每个出队的点依次遍历每个与他有边相邻的点(用邻接表效率较高),如果该点可以松弛并且队列中没有该点则将它加入队列中(只有进行松弛操作的点才会对它的邻接点有影响,也就是说其邻接点才需要松弛操作),如此迭代直到队列为空。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #define maxn 105 #define MAXN 1005 using namespace std; int n,m,ans,cnt,sx; bool vis[maxn]; int dist[maxn],p[maxn]; struct Node { int r,cost,next; }edge[MAXN]; void init() { memset(vis,0,sizeof(vis)); memset(p,0,sizeof(p)); memset(dist,0x3f,sizeof(dist)); } void addedge(int u,int v,int w) { cnt++; edge[cnt].r=v; edge[cnt].cost=w; edge[cnt].next=p[u]; p[u]=cnt; } void SPFA() { int i,j,nx; sx=1; queue<int>q; dist[sx]=0; vis[sx]=1; q.push(sx); while(!q.empty()) { nx=q.front(); vis[nx]=0; q.pop(); for(i=p[nx];i;i=edge[i].next) { if(dist[edge[i].r]>dist[nx]+edge[i].cost) { dist[edge[i].r]=dist[nx]+edge[i].cost; if(!vis[edge[i].r]) { vis[edge[i].r]=1; q.push(edge[i].r); } } } } } int main() { int i,j,u,v,w; while(~scanf("%d%d",&n,&m)) { init(); cnt=0; for(i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } SPFA(); for(i=1;i<=n;i++) printf("i:%d dist:%d\n",i,dist[i]); } return 0; }
7 9 1 2 3 2 4 1 3 4 4 4 6 2 3 6 8 6 7 5 4 5 6 5 7 7 1 3 2
spfa学习
最新推荐文章于 2022-07-03 17:06:52 发布