POJ 3255 Wormholes(最短路最负环)
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 20639 | Accepted: 7342 |
Description
While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..N, M (1 ≤ M ≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.
As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .
To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.
Input
Line 1 of each farm: Three space-separated integers respectively: N, M, and W
Lines 2..M+1 of each farm: Three space-separated numbers (S, E, T) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path.
Lines M+2..M+W+1 of each farm: Three space-separated numbers (S, E, T) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds.
Output
Sample Input
2 3 3 1 1 2 2 1 3 4 2 3 1 3 1 3 3 2 1 1 2 3 2 3 4 3 1 8
Sample Output
NO YES
Hint
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.
Source
/* POJ 3259 就是判断负环回路。 用SPFA和BellmanFord都可以 但是一直想不通的是题目要求是要回到出发点, 有负环可能回不去啊。。。。数据弱爆了。。。Orz */ // G++ 732K 94ms #include<stdio.h> #include<iostream> #include<algorithm> #include<iostream> using namespace std; const int MAXN=550; const int MAXE=5050; const int INF=0x3f3f3f3f; int dist[MAXN]; int edge[MAXE][3]; int tol; bool bellman(int start,int n) { for(int i=1;i<=n;i++)dist[i]=INF; dist[start]=0; for(int i=1;i<n;i++) { bool flag=false; for(int j=0;j<tol;j++) { if(dist[edge[j][1]]>dist[edge[j][0]]+edge[j][2]) { dist[edge[j][1]]=dist[edge[j][0]]+edge[j][2]; flag=true; } } if(!flag)return false;//没有负环 } for(int j=0;j<tol;j++) if(dist[edge[j][1]]>dist[edge[j][0]]+edge[j][2]) return true; return false; } int main() { int n,M,W; int a,b,c; int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&M,&W); tol=0; while(M--) { scanf("%d%d%d",&a,&b,&c); edge[tol][0]=a; edge[tol][1]=b; edge[tol][2]=c; tol++; edge[tol][0]=b; edge[tol][1]=a; edge[tol][2]=c; tol++; } while(W--) { scanf("%d%d%d",&a,&b,&c); edge[tol][0]=a; edge[tol][1]=b; edge[tol][2]=-c; tol++; } if(bellman(1,n))printf("YES\n"); else printf("NO\n"); } return 0; }
SPFA:
/* POJ 3259 SPFA判断负环 */ //G++ 756K 157ms #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; const int MAXN=550; const int MAXE=5050;//这个5000会RE const int INF=0x3f3f3f3f; int head[MAXN]; int dist[MAXN]; int cnt[MAXN]; int que[MAXN]; bool vis[MAXN]; struct edge { int to; int next; int v; }edge[MAXE]; int tol; void add(int a,int b,int c) { edge[tol].to=b; edge[tol].v=c; edge[tol].next=head[a]; head[a]=tol++; } bool SPFA(int start,int n) { int front=0,rear=0; for(int v=1;v<=n;v++) { if(v==start) { dist[v]=0; que[rear++]=v; vis[v]=true; cnt[v]=1; } else { dist[v]=INF; vis[v]=false; cnt[v]=0; } } while(front!=rear) { int u=que[front++]; vis[u]=false; if(front>=MAXN)front=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(dist[v]>dist[u]+edge[i].v) { dist[v]=dist[u]+edge[i].v; if(!vis[v]) { vis[v]=true; que[rear++]=v; if(rear>=MAXN)rear=0; if(++cnt[v]>n)return true; } } } } return false; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int n,M,W; int a,b,c; int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&M,&W); tol=0; memset(head,-1,sizeof(head));//这个不能忘记!!! while(M--) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } while(W--) { scanf("%d%d%d",&a,&b,&c); add(a,b,-c); } if(SPFA(1,n))printf("YES\n"); else printf("NO\n"); } return 0; }