Bellman-Ford SPFA算法

适用范围

单源最短路(可判负圈).

原理

Bellman-Ford算法核心思想:动态规划.d[i]的定义为起点s到第i个点的最短距离.刚开始d[i]数组初始化为INF,d[s]=0.然后遍历所有的边,把所有能更新的点更新一遍,能更新的点判定条件为d[to]>d[from]+w(边权),能更新则更新为d[to]=d[from]+w.这种更新方法最多更新V-1次,因为更新n次就能找到由n条边组成的最短路,而图中不存在由V条边组成的最短路(除非存在负环),因此bellman_ford可以判负环.复杂度O(VE)(V点E边).

代码

 1 struct edge{int from,to,cost;};
 2 edge es[MAX];
 3 int d[MAX];
 4 int V,E;
 5 
 6 bool Bellman_Ford(int s) //起点 如果存在负环返回true,否则返回true
 7 {
 8     for(int i=1;i<=V;i++) d[i]=INF_INT; //点从1开始编号
 9     d[s]=0;
10     int cnt=0; //用来数更新多少次
11     while(true)
12     {
13         bool update=false;
14         for(int i=0;i)
15         {
16             edge e=es[i];
17             if(d[e.from]!=INF_INT&&d[e.to]>d[e.from]+e.cost)
18             {
19                 d[e.to]=d[e.from]+e.cost;
20                 update=true;
21             }
22         }
23         if(!update||cnt>=V) break;
24         cnt++;
25     }
26     if(cnt>=V) return true;
27     return false;
28 }

扩展

事实上SPFA算法就是在bellman_ford的基础上加个队列优化,也具有判负环的功能.一般复杂度O(ElogV).但这个优化最差复杂度跟bellman_ford一样为O(VE).

 1 typedef pair<int,int> P;
 2 struct edge{int to,cost;};
 3 vector es[MAX];
 4 bool vis[MAX];
 5 int d[MAX];
 6 int V,E;
 7 
 8 bool SPFA(int s) //s为起点 存在负环返回true,否则返回false
 9 {
10     queue

que; 11 for(int i=1;i<=V;i++) d[i]=INF_INT,vis[i]=false; //点编号从1开始 12 d[s]=0;vis[s]=true; 13 que.push(P(s,0)); 14 while(que.size()) 15 { 16 P p=que.front();que.pop(); 17 if(p.second>=V) return true; 18 int x=p.first; 19 vis[x]=false; 20 for(int i=0;i) 21 { 22 edge e=es[x][i]; 23 if(d[e.to]>d[x]+e.cost) 24 { 25 d[e.to]=d[x]+e.cost; 26 if(!vis[e.to]) que.push(P(e.to,p.second+1)); 27 } 28 } 29 } 30 return false; 31 }

 

转载于:https://www.cnblogs.com/VBEL/p/11487993.html

你可能感兴趣的:(数据结构与算法)