Wormholes POJ 3259(负回路)
原题
题目分析
题目要求判断是否存在一条回路,使得回路的距离之和为负数,其实就是图中是否存在负圈,因此可以用bellman来判负圈,如果bellman更新了n次则证明出现负圈,因为n个点构成的图最多只能有由n-1条边构成的最短路.bellman跑了n次则证明存在n条边构成的最短路.
代码
1 #include <iostream> 2 #include <algorithm> 3 #include <utility> 4 #include <cstdio> 5 #include <cmath> 6 #include <cstring> 7 #include <string> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <map> 12 #include <set> 13 14 using namespace std; 15 typedef long long LL; 16 const int INF_INT=0x3f3f3f3f; 17 const LL INF_LL=0x3f3f3f3f3f3f3f3f; 18 19 typedef pair<int,int> P; 20 int n,m,w; 21 int edge[600][600]; 22 int dis[600]; 23 bool vis[600]; 24 25 void bell(int n) 26 { 27 for(int i=1;i<=n;i++) dis[i]=INF_INT,vis[i]=false; 28 queue<P> que; 29 que.push(P(1,0)); 30 dis[1]=0; 31 vis[1]=true; 32 while(que.size()) 33 { 34 P p=que.front();que.pop(); 35 if(p.second>=n) 36 { 37 printf("YES\n"); 38 return ; 39 } 40 vis[p.first]=false; 41 for(int i=1;i<=n;i++) 42 if(dis[i]>dis[p.first]+edge[p.first][i]) 43 { 44 dis[i]=dis[p.first]+edge[p.first][i]; 45 if(!vis[i]) que.push(P(i,p.second+1)); 46 } 47 } 48 printf("NO\n"); 49 return ; 50 } 51 52 int main() 53 { 54 // freopen("black.in","r",stdin); 55 // freopen("black.out","w",stdout); 56 int t; 57 scanf("%d",&t); 58 while(t--) 59 { 60 scanf("%d %d %d",&n,&m,&w); 61 for(int i=1;i<=n;i++) 62 for(int j=1;j<=n;j++) edge[i][j]=INF_INT; 63 for(int i=0;i<m;i++) 64 { 65 int x,y,c; 66 scanf("%d %d %d",&x,&y,&c); 67 edge[x][y]=min(edge[x][y],c); 68 edge[y][x]=min(edge[y][x],c); 69 } 70 for(int i=0;i<w;i++) 71 { 72 int x,y,c; 73 scanf("%d %d %d",&x,&y,&c); 74 edge[x][y]=min(edge[x][y],-1*c); 75 } 76 bell(n); 77 } 78 return 0; 79 }