题意:虫洞是很奇特的,因为它是一个**单向**通道,可让你进入虫洞的前达到目的地!他的N(1≤N≤500)个农场被编号为1..N,之间有M(1≤M≤2500)条路径,W(1≤W≤200)个虫洞。FJ作为一个狂热的时间旅行的爱好者,他要做到以下几点:开始在一个区域,通过一些路径和虫洞旅行,他要回到最开时出发的那个区域出发前的时间。也许他就能遇到自己了:)。为了帮助FJ找出这是否是可以或不可以,他会为你提供F个农场的完整的图(1≤F≤5)。所有的路径所花时间都不大于10000秒,所有的虫洞都回到不大于10000秒之前。

AC代码:

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
#include <algorithm>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
int tot,dis[maxn],head[maxn],num[maxn],vis[maxn];
int n,m,w;
struct node {
int v,w,nxt;
} e[maxn];
void add(int u,int v,int w) {
e[tot].v=v;
e[tot].w=w;
e[tot].nxt=head[u];
head[u]=tot++;
}
bool spfa() {
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
queue<int>q;
dis[1]=0;
for(int i=1;i<=n;i++)q.push(i),vis[i]=1;
while(q.size()) {
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u]; i!=-1; i=e[i].nxt) {
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w) {
dis[v]=dis[u]+e[i].w;
num[v]=num[u]+1;
if(num[v]>n)return true;
if(!vis[v]) {
vis[v]=1;
q.push(v);
}
}
}
}
return false;
}
main() {
IOS;
int t;
cin>>t;
while(t--) {
cin>>n>>m>>w;
tot=1;
memset(head,-1,sizeof(head));
for(int i=1; i<=n; i++)dis[i]=inf;
for(int i=1; i<=m; i++) {
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
add(y,x,z);
}
for(int i=1; i<=w; i++) {
int x,y,z;
cin>>x>>y>>z;
add(x,y,-z);
}
if(spfa())cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}