标签:否则 div cond 条件 优化 mil 编号 size typedef
单源最短路(可判负圈).
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<E;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<edge> 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<P> 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<es[x].size();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 }
标签:否则 div cond 条件 优化 mil 编号 size typedef
原文地址:https://www.cnblogs.com/VBEL/p/11487993.html