http://poj.org/problem?id=3259
农夫john发现了一些虫洞,虫洞是一种在你到达虫洞之前把你送回目的地的一种方式,FJ的每个农场,由n块土地(编号为1-n),M
条路,和W个 虫洞组成,FJ想从一块土地开始,经过若干条路和虫洞,返回到他最初开始走的地方并且时间要在他离开之前,或者恰好等于他离开的时间。
把虫洞的时间看成负边权,就是判断从起点出发是否存在负权回路。那么就可以采用bellman-ford算法,注意数组开大点。
1 /* *********************************************** 2 Author : zch 3 Created Time :2015/5/13 19:37:22 4 File Name :poj - 3259 Wormholes 5 ************************************************ */ 6 7 #include <cstdio> 8 #include <cstring> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <cmath> 17 #include <cstdlib> 18 #include <ctime> 19 using namespace std; 20 const int maxn = 1010; 21 const int maxv = 5000; 22 const int INF = 1<<29; 23 struct edge{int from,to,cost;}; 24 edge es[maxv]; 25 int d[maxn]; 26 int N,M,W; 27 int edgenum; 28 29 bool short_path(int s) { 30 for(int i=1;i<=N;i++) d[i]=INF; 31 d[s]=0; 32 for(int i=0;i<N;i++) { 33 bool flag=false; 34 for(int j=0;j<edgenum;j++) { 35 edge e=es[j]; 36 if(d[e.from]!=INF&&d[e.to]>d[e.from]+e.cost) { 37 d[e.to]=d[e.from]+e.cost; 38 flag=true; 39 if(i==N-1) return true; //如果 第n次仍然更新了,则存在负圈。 40 } 41 } 42 if(!flag) break; 43 } 44 return false; 45 } 46 47 int main() 48 { 49 //freopen("a.txt","r",stdin); 50 //freopen("b.txt","w",stdout); 51 int F,a,b,c; 52 scanf("%d",&F); 53 while(F--) { 54 scanf("%d%d%d",&N,&M,&W); 55 edgenum=0; 56 for(int i=0;i<M;++i) { //普通路径是双向的 57 scanf("%d%d%d",&a,&b,&c); 58 es[edgenum].from=a;es[edgenum].to=b;es[edgenum++].cost=c; 59 es[edgenum].from=b;es[edgenum].to=a;es[edgenum++].cost=c; 60 } 61 for(int i=0;i<W;++i) { //虫洞是单向的。 62 scanf("%d%d%d",&a,&b,&c); 63 es[edgenum].from=a;es[edgenum].to=b;es[edgenum++].cost=-c; 64 } 65 bool flag=short_path(1); 66 if(flag) printf("YES\n"); 67 else printf("NO\n"); 68 } 69 return 0; 70 }