POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
2017-08-08 16:57
531 查看
题意:要求判断任意两点都能仅通过正边就可互相到达的有向图中是否存在负权环
Bellman-Ford的模板题目。
无论中间是否出现重复,进行N-1次循环。
中间出现重复,立即结束N-1次循环得到结果
此份代码在数据较大的时候可以节省大量时间,推荐使用
下面介绍一种SPFA的算法,是Bellman-Ford算法的改进版,利用动态队列更新dist
Bellman-Ford的模板题目。
无论中间是否出现重复,进行N-1次循环。
#include <iostream> #include <vector> using namespace std; int F,N,M,W; const int INF = 1<<30; struct Edge { int s,e,w; Edge(int ss,int ee,int ww):s(ss),e(ee),w(ww) {} Edge() {} }; vector <Edge> edges; //所有的边 int dist[1000]; int Bellman_ford(int v) { for(int i=1;i<=N;++i) dist[i]=INF; dist[v]=0; for(int k=1;k<N;++k) //经过不超过K条边 for(int i=0;i<edges.size();++i) { int s=edges[i].s; int e=edges[i].e; if(dist[s]+edges[i].w<dist[e]) dist[e]=dist[s]+edges[i].w; } //再进行一次松弛操作,检查是否有负权边,如果某点路径更短,则有负权边 for(int i=0;i<edges.size();i++) { int s=edges[i].s; int e=edges[i].e; if(dist[s]+edges[i].w<dist[e]) return true; } return false; } int main() { cin>>F; while(F--) { edges.clear(); cin>>N>>M>>W; //存贮各条边 for(int i=0;i<M;++i) { int s,e,t; cin>>s>>e>>t; edges.push_back(Edge(s,e,t));//双向边等于两条边 edges.push_back(Edge(e,s,t)); } for(int i=0;i<W;i++) { int s,e,t; cin>>s>>e>>t; edges.push_back(Edge(s,e,-t));//单向负权边 } if(Bellman_ford(1)) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
中间出现重复,立即结束N-1次循环得到结果
#include <iostream> #include <vector> using namespace std; int F,N,M,W; const int INF = 1<<30; struct Edge { int s,e,w; Edge(int ss,int ee,int ww):s(ss),e(ee),w(ww) {} Edge() {} }; vector <Edge> edges; //所有的边 int dist[1000]; int Bellman_ford(int v) { for(int i=1;i<=N;++i) dist[i]=INF; dist[v]=0; for(int k=1;k<N;++k){ //N-1次松弛操作 bool flag=false; for(int i=0;i<edges.size();++i){ int s=edges[i].s; int e=edges[i].e; if(dist[s]+edges[i].w<dist[e]){ dist[e]=dist[s]+edges[i].w; flag=true; } } if(!flag) break; } //再进行一次松弛操作,检查是否有负权边,如果某点路径更短,则有负权边 for(int i=0;i<edges.size();i++) { int s=edges[i].s; int e=edges[i].e; if(dist[s]+edges[i].w<dist[e]) return true; } return false; } int main() { cin>>F; while(F--) { edges.clear(); cin>>N>>M>>W; //存贮各条边 for(int i=0;i<M;++i) { int s,e,t; cin>>s>>e>>t; edges.push_back(Edge(s,e,t));//双向边等于两条边 edges.push_back(Edge(e,s,t)); } for(int i=0;i<W;i++) { int s,e,t; cin>>s>>e>>t; edges.push_back(Edge(s,e,-t));//单向负权边 } if(Bellman_ford(1)) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
此份代码在数据较大的时候可以节省大量时间,推荐使用
下面介绍一种SPFA的算法,是Bellman-Ford算法的改进版,利用动态队列更新dist
#include <iostream> #include <vector> #include <queue> #include <cstring> using namespace std; int F,N,M,W; const int INF =1<<30; struct Edge{ int e,w; Edge(int ee,int ww):e(ee),w(ww){ } Edge() {} }; vector <Edge> G[1000]; //整个有向图 int updateTimes[1000]; //最短路的改进次数 int dist[1000]; //dist[i]是源到i的目前的最短路长度 int Spfa(int v){ for(int i=1;i<=N;i++) dist[i]=INF; dist[v]=0; //源点 queue<int>que; //定义队列 que.push(v); //源点加入队列 memset(updateTimes,0,sizeof(updateTimes)); while(!que.empty()){ int s=que.front(); que.pop(); for(int i=0;i<G[s].size();i++){ int e=G[s][i].e; if(dist[e]>dist[s]+G[s][i].w){ dist[e]=dist[s]+G[s][i].w; que.push(e); ++updateTimes[e]; if(updateTimes[e]>=N) return true; } } } return false; } int main() { cin>>F; while(F--){ cin>>N>>M>>W; for(int i=1;i<1000;i++) G[i].clear(); int s,e,t; for(int i=0;i<M;i++){ cin>>s>>e>>t; G[s].push_back(Edge(e,t)); G[e].push_back(Edge(s,t)); } for(int i=0 ;i<W;i++){ cin>>s>>e>>t; G[s].push_back(Edge(e,-t)); } if(Spfa(1)) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
相关文章推荐
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- [ACM] POJ 3259 Wormholes (bellman-ford最短路径,判断是否存在负权回路)
- Wormholes( POJ 3259)(Bellman-Ford+SPFA)(判断是否有负权环)(最短路模板)
- POJ 3259 Wormholes(Bellman-Ford判断是否有负权边)
- [ACM] POJ 3259 Wormholes (bellman-ford最短路径,推断是否存在负权回路)
- POJ 3259 Wormholes(判断负权回路|SPFA||Bellman-Ford)
- poj 3259 Wormholes 【spfa判断是否存在负环】
- POJ No 3259 Wormholes Bellman-Ford 判断是否存在负图
- poj 3259 bellman-ford算法 判断是否存在负权回路
- (POJ 3259)Wormholes 判断负环 bellman_ford 或者 spfa
- POJ 3259 Wormholes (判断负环,SPFA或Bellman-Ford都可)
- POJ - 3259 Wormholes解题报告(Bellman-Ford判断有向图中是否有负权环)
- POJ 3259 Wormholes(判断负环&(Bellman-Ford|SPFA))
- poj1860(Bellman-Ford变形,含负权的单源最短路径,判断是否有正权环)
- Bellman_ford和SPFA判断是否存在负环