bzoj 1715: [Usaco2006 Dec]Wormholes 虫洞 — spfa判断负环
Contents
1715: [Usaco2006 Dec]Wormholes 虫洞
Time Limit: 5 Sec Memory Limit: 64 MB
Description
John在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。John的每个农场有M条小路(无向边)连接着N (从1..N标号)块地,并有W个虫洞。其中1<=N<=500,1<=M<=2500,1<=W<=200。 现在John想借助这些虫洞来回到过去(出发时刻之前),请你告诉他能办到吗。 John将向你提供F(1<=F<=5)个农场的地图。没有小路会耗费你超过10000秒的时间,当然也没有虫洞回帮你回到超过10000秒以前。
Input
* Line 1: 一个整数 F, 表示农场个数。
* Line 1 of each farm: 三个整数 N, M, W。
* Lines 2..M+1 of each farm: 三个数(S, E, T)。表示在标号为S的地与标号为E的地中间有一条用时T秒的小路。
* Lines M+2..M+W+1 of each farm: 三个数(S, E, T)。表示在标号为S的地与标号为E的地中间有一条可以使John到达T秒前的虫洞。
Output
* Lines 1..F: 如果John能在这个农场实现他的目标,输出”YES”,否则输出”NO”。
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
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
YES
HINT
Source
注意第一次加边是双向边第二次是单向边,并且每次询问前数组要清空
#include<queue> #include<cstdio> #include<cstring> #include<iostream> using namespace std; #define N 510 inline int read() { int x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } struct qaz{int fro,to,v;}e[100010]; int f,n,m,w,S,E,V,cnt,lj[N],dis[N],sum[N]; bool used[N]; void add(int a,int b,int c){cnt++;e[cnt].fro=lj[a];e[cnt].to=b;e[cnt].v=c;lj[a]=cnt;} queue<int>q; bool spfa() { memset(dis,127/3,sizeof(dis)); memset(used,0,sizeof(used)); memset(sum,0,sizeof(sum)); q.push(1); used[1]=1; dis[1]=0; while(!q.empty()) { int t=q.front();q.pop(); used[t]=0; for(int i=lj[t];i;i=e[i].fro) { int et=e[i].to; if(e[i].v+dis[t]<dis[et]) { sum[et]++; if(sum[et]>n) return 1; dis[et]=e[i].v+dis[t]; if(!used[et]) { q.push(et); used[et]=1; } } } } return 0; } int main() { f=read(); while(f--) { n=read();m=read();w=read(); memset(lj,0,sizeof(lj)); for(int i=0;i<m;i++) { S=read();E=read();V=read(); add(S,E,V);add(E,S,V); } for(int i=0;i<w;i++) { S=read();E=read();V=read(); add(S,E,-V); } if(spfa()) puts("YES"); else puts("NO"); } }
发表评论