题目大意:有n个村庄,村庄之间有m条正常的路,有w条时光隧道,隧道的权值为负数即时空倒流,问你他能否回到起始点看到自己。
算法思想:只要从任意一点出发,看这个点出发是否有负环,并且这个负环是回到起始点的。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define INF 0x3f3f3f3f typedef struct Edge { int u; int v; int c; }; Edge edges[5050]; bool visited[505],isOver; int next[5050],head[505],dist[505],num[505]; int t; int n,m,w,e; int a,b,c; int a1,b1,c1; void addNode(int u,int v,int c) { edges[e].u=u; edges[e].v=v; edges[e].c=c; next[e]=head[u]; head[u]=e++; } bool relax(int u,int v,int c) { if(dist[v]>dist[u]+c) { dist[v]=dist[u]+c; return true; } return false; } bool spfa(int src) { for(int i=1;i<=n;i++) { dist[i]=INF; } dist[src]=0; memset(visited,false,sizeof(visited)); memset(num,0,sizeof(num)); visited[src]=true; queue<int>que; que.push(src); while(!que.empty()) { int q=que.front(); que.pop(); visited[q]=false; for(int i=head[q];i+1;i=next[i]) { if(relax(q,edges[i].v,edges[i].c)&&!visited[edges[i].v]) { if(++num[edges[i].v]>n) return false; visited[edges[i].v]=true; que.push(edges[i].v); } } } return true; } int main() { scanf("%d",&t); while(t--) { memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); memset(edges,0,sizeof(edges)); e=0;isOver=false; scanf("%d%d%d",&n,&m,&w); for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); addNode(a,b,c); addNode(b,a,c); } for(int i=0;i<w;i++) { scanf("%d%d%d",&a1,&b1,&c1); addNode(a1,b1,-c1); } for(int i=1;i<=n;i++) { if(!spfa(i)&&dist[i]<=0) { isOver=true; printf("YES\n"); break; } } if(!isOver) printf("NO\n"); } return 0; }