Bzoj1715虫洞
Posted wwhhtt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj1715虫洞相关的知识,希望对你有一定的参考价值。
试题描述
|
John 在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。John 的每个农场有 M 条小路(无向边)连接着 N(从 1 到 N 标号)块地,并有 W 个虫洞。
现在 John 想借助这些虫洞来回到过去(在出发时刻之前回到出发点),请你告诉他能办到吗。 John 将向你提供 F 个农场的地图。没有小路会耗费你超过 10^4秒的时间,当然也没有虫洞回帮你回到超过 10^4秒以前。 |
输入
|
第一行一个整数 F,表示农场个数;
对于每个农场: 第一行,三个整数 N,M,W; 接下来 M 行,每行三个数 S,E,T,表示在标号为 S 的地与标号为 E 的地中间有一条用时 T 秒的小路; 接下来 W 行,每行三个数 S,E,T,表示在标号为 S 的地与标号为 E 的地中间有一条可以使 John 到达 T 秒前的虫洞。 |
输出
|
输出共 F 行,如果 John 能在第 i 个农场实现他的目标,就在第 i 行输出 YES,否则输出 NO。
|
输入示例
|
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 |
其他说明
|
对于全部数据,1≤F≤5,1≤N≤500,1≤M≤2500,1≤W≤200,1≤S,E≤N,∣T∣≤104。
|
题目描述还是很清晰的,大概就是给一个图,判断图中是否存在负环,简单的一个SPFA就可以跑
然而要注意的是,这道题用普通的BFS会被卡(不知道SLF能不能过,有兴趣的同学可以试一下)
判断负环的方法很简单,如果我们发现一个点已经被更新过了,但是dis值却比当前点还要小,就证明它从这个点出发后,跑了一个小于零的路径又回到了原点,证明有负环
下面给出代码
#include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #define cl(a) memset(a,0,sizeof(a)) using namespace std; inline int rd(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘; return x*f; } inline void write(int x){ if(x<0) putchar(‘-‘),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); return ; } int T; int n,m,w; int total=0; int head[10006],nxt[10006],to[10006],v[10006]; int dis[1006]; void add(int x,int y,int z){ total++; to[total]=y; v[total]=z; nxt[total]=head[x]; head[x]=total; return ; } int book[1006]; int f=0; void SPFA(int x){//DFS版的SFPA for(int e=head[x];e;e=nxt[e]){ if(dis[to[e]]>dis[x]+v[e]){ dis[to[e]]=dis[x]+v[e]; if(book[to[e]]){//如果一个点已经跑过了,但是值比原来还要小,就是负环 f=1; return ; } book[to[e]]=1; SPFA(to[e]); book[to[e]]=0; } } return ; } int main(){ T=rd(); while(T--){ f=0; total=0; cl(head),cl(nxt),cl(to),cl(v),cl(book); memset(dis,127,sizeof(dis)); n=rd(),m=rd(),w=rd(); for(int i=1;i<=m;i++){ int x,y,z; x=rd(),y=rd(),z=rd(); add(x,y,z); add(y,x,z); } for(int i=1;i<=w;i++){ int x,y,z; x=rd(),y=rd(),z=rd(); add(x,y,0-z);//虫洞因为是往回倒时间,所以存成负数 } dis[1]=0; SPFA(1); if(f) printf("YES "); else printf("NO "); } return 0; }
以上是关于Bzoj1715虫洞的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ1715][Usaco2006 Dec]Wormholes 虫洞