1507:虫洞 Wormholes
作者:互联网
【题目描述】
原题来自:USACO 2006 Dec. Gold,原文见 POJ 3259
John 在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。John 的每个农场有 M 条小路(无向边)连接着 N(从 1 到 N 标号)块地,并有 W 个虫洞。
现在 John 想借助这些虫洞来回到过去(在出发时刻之前回到出发点),请你告诉他能办到吗。 John 将向你提供 F 个农场的地图。没有小路会耗费你超过 104秒的时间,当然也没有虫洞回帮你回到超过 104 秒以前。
【输入】
第一行一个整数 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即可。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;
const int N=5210;
int h[N],ne[N],e[N],idx,w[N],dist[N];
bool st[N];
int t;
int n,m,ww;
int cnt[N];
void add(int a,int b,int c){
e[idx]=b; w[idx]=c; ne[idx]=h[a]; h[a]=idx++;
}
bool spfa(){
queue <int> q;
memset(dist,0x3f,sizeof(dist));
for (int i = 1; i <= n; i ++ )
{
q.push(i);
st[i] = true;
}
while(q.size()){
int t=q.front(); q.pop();
st[t]=0;
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(dist[j]>dist[t]+w[i]){
dist[j]=dist[t]+w[i];
cnt[j]=cnt[t]+1;
if(cnt[j]>=n){
return 0;//当一个点进入队列超过n次时说明有负权回路。
}
if(!st[j]){
st[j]=1;
q.push(j);
}
}
}
}
return 1;
}
int main(){
cin>>t;
while(t--){
memset(h,-1,sizeof(h));
memset(st,0,sizeof(st));
memset(cnt,0,sizeof(cnt));
idx=0;
cin>>n>>m>>ww;
for(int i=1;i<=m;i++){
int a,b,c;
cin >> a >> b >> c;
add(a,b,c);
add(b,a,c);
}
for(int i=1;i<=ww;i++){
int a,b,c;
cin >> a >> b >> c;
add(a,b,-1*c);//边权要取正
}
if (!spfa()) cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
标签:cnt,include,dist,idx,int,1507,Wormholes,John 来源: https://www.cnblogs.com/lyc-lb-blogs/p/14969972.html