题目大意:
农场上有N块田地(N < = 500),M条路径(M <= 2500)可以从i到达j花费t单位时间。另外还有W个虫洞(W <= 200),虫洞可以从一块地i到达另一块地j并且时间倒退t!注意路径是双向的,虫洞是单向的。现在农夫John希望知道能否从某块地出发并且回到这块地,使得他回来的时间早于出发的时间(可以遇到他自己^^)。
分析:
褪去题目的伪装,可以看出,题目就是要求一个带负权的有向图中是否存在权值为负的回路。
这个问题就是Bellman-Ford求带负权有向图的最短路径时,需要解决的问题。
- /*
- PKU3259 Wormholes
- */
- #include <stdio.h>
- #include <memory.h>
- #define clr(a) memset(a,0,sizeof(a))
- #define INF (1<<28)
- #define N 505
- #define M 6005
- int Bellman_Ford(int e[][3],int m,int n,int d[])
- {
- int k,v,flag,i,j;
- for(k=0;k<n;k++) d[k]=INF;
- //d[0]=0;
- for(k=0;k<n-1;k++)
- {
- flag=0;
- for(v=0;v<m;v++){
- i=e[v][0]; j=e[v][1];
- if(d[j]>d[i]+e[v][2]){
- d[j]=d[i]+e[v][2];
- flag=1;
- }
- }
- if(!flag) return 1;
- }
- for(v=0;v<m;v++)
- if(d[e[v][1]]>d[e[v][0]]+e[v][2])
- return 0;
- return 1;
- }
- int n,m,w;
- int e[M][3],ne;
- int d[N];
- void addEdge(int i,int j,int k){
- e[ne][0]=i;
- e[ne][1]=j;
- e[ne][2]=k;
- ne++;
- }
- int main()
- {
- int i,j,k,t,T;
- scanf("%d",&T);
- while(T--){
- //input
- ne=0;
- scanf("%d%d%d",&n,&m,&w);
- for(k=0;k<m+w;k++){
- scanf("%d%d%d",&i,&j,&t);
- if(k<m){
- addEdge(i,j,t);
- addEdge(j,i,t);
- }
- else{
- addEdge(i,j,-t);
- }
- }
- //output
- if(Bellman_Ford(e,ne,n,d)) puts("NO");
- else puts("YES");
- }
- return 0;
- }