POJ3259 :Wormholes(SPFA判负环)
POJ3259 :Wormholes
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.
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.
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
NO YES
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.
FJ的农场有很多虫洞,可以实现时光倒流,现在给你农场每条道路的起点、终点和时间,还有虫洞的起点、终点和能倒流的
时间,问FJ能不能通过时光倒流看到之前的自己。
首先T组数据,再输入n,m,w 分别代表n个节点,m个无向边的信息,w个有向虫洞的信息
思路:
把w个虫洞当负值加进边就行
比如第一组数据的3 1 3,在构图的时候add_edge(3,1,-3),即可。
其实就是用spfa跑一遍图,看一下有没有负环即可。有的话输出YES,没有的话输出NO
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<cmath> #include<vector> #include<cstring> using namespace std; typedef long long LL; #define Max_N 1001 #define INF 100000000 int head[Max_N],vis[Max_N],n,In[Max_N],cnt; int dis[Max_N]; int pa[Max_N]; struct note{ int from,to,next; int c; }edge[50005*2]; void init(){ memset(head,-1,sizeof(head)); cnt = 0; } void add_edge(int u,int v,double c){ edge[cnt].from = u; edge[cnt].to = v; edge[cnt].c = c; edge[cnt].next = head[u]; head[u] = cnt++; } bool spfa(int s,int n,int key){ queue<int>q; for(int i = 0 ;i <= n ; i++) dis[i] = INF; memset(vis,0,sizeof(vis)); memset(In,0,sizeof(In)); q.push(s); vis[s] = 1; dis[s] = 0; if(key == -1) memset(pa,-1,sizeof(pa)); while(!q.empty()){ int p = q.front(); vis[p] = 0; q.pop(); for(int i = head[p] ; ~i ; i = edge[i].next){ if(key==i)continue; int temp = edge[i].to; if(dis[temp] > dis[p] + edge[i].c){ dis[temp] = dis[p] + edge[i].c; if(key==-1) pa[temp] = i; if(!vis[temp]){ q.push(temp); vis[temp] = 1; if(++In[temp]>n)return false; } } } } return true; }//spfa带记录路径,通过Key调整 int main(){ int m,t,w; for(scanf("%d",&t);t--;){ scanf("%d %d %d",&n,&m,&w); init(); int x,y,c; for(int i = 0 ; i < m ; i++){ scanf("%d %d %d",&x,&y,&c); add_edge(x,y,c); add_edge(y,x,c); } for(int i = 0 ; i < w ; i++){ scanf("%d %d %d",&x,&y,&c); add_edge(x,y,-c); } spfa(1,n,-1)?puts("NO"):puts("YES"); } return 0; }