/*题意:John的农场里有n块地和m条路双向路以及w个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退T秒。我们的任务是知道会不会在从某块地出发后又回来,看到了离开之前的自己。 说下输入:n块地,m条边,w个虫洞。下面依次是m条边的信息(双向),输入完后是w个虫洞的信息(单向)。 思路:spfa。由于存在负权边,Dijkstra便不能用了。简化题目->就是看图中有没有负权环,有的话John可以无限次走这个环,使得时间一定能得到一个负值。所以存在负环话就是可以,没有的话就是不可以了。*/ #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<queue> using namespace std; const int inf=1<<29; const int maxn=2505; const int maxm=maxn*maxn; int next[maxm],cost[maxm],data[maxm],cnt[maxn],pre[maxn],head[maxm]; int vis[maxn],e,dist[maxm]; int n,m,w; queue<int>q; void addage(int u,int v,int c) { data[e]=v; cost[e]=c; next[e]=head[u]; head[u]=e++; } int spfa(int st) { for(int i=0; i<=n; i++) { dist[i]=inf; } dist[st]=0; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u]; i!=-1; i=next[i]) { if(dist[data[i]]>dist[u]+cost[i]) { pre[data[i]]=u; dist[data[i]]=dist[u]+cost[i]; if(!vis[data[i]]) { if(++cnt[data[i]]==n) return 1; q.push(data[i]); vis[data[i]]=1; } } } } return 0; } int main() { int y; scanf("%d",&y); while(y--) { scanf("%d%d%d",&n,&m,&w); e=0; int i,j; memset(vis,0,sizeof(vis)); memset(cnt,0,sizeof(cnt)); memset(pre,-1,sizeof(pre)); memset(head,-1,sizeof(head)); int u,v,c; while(m--) { scanf("%d%d%d",&u,&v,&c); addage(u,v,c); addage(v,u,c); } while(w--) { scanf("%d%d%d",&u,&v,&c); addage(u,v,-c); } int ok=1; if(spfa(1)) { printf("YES\n"); } else { printf("NO\n"); } } return 0; }