题意:
农夫john发现了一些虫洞,虫洞是一种在你到达虫洞之前把你送回目的地的一种方式,FJ的每个农场,由n块土地(编号为1-n),M
条路,和W个 虫洞组成,FJ想从一块土地开始,经过若干条路和虫洞,返回到他最初开始走的地方并且时间要在他离开之前,或者恰好等于他离开的时间。
把虫洞的时间看成负边权,就是是否存在负权回路。 虽然题中没有说明起点和终点 但从1开始即可 因为无论从哪个点开始 有没有负环的情况都是一样的
spfa 判断负环:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long LL; const int maxn = 1001, INF = 0xfffffff; int vis[maxn], d[maxn], head[maxn], ans[maxn]; int n, m, p; struct node{ int u,v,w,next; }Node[maxn]; void add(int u,int v,int w,int i) { Node[i].u = u; Node[i].v = v; Node[i].w = w; Node[i].next = head[u]; head[u] = i; } int spfa(int s) { queue<int> Q; mem(vis,0); for(int i=0; i<=n; ++i) d[i] = INF; d[s] = 0; Q.push(s); vis[s] = 1; while(!Q.empty()) { int x = Q.front(); Q.pop(); vis[x] = 0; for(int i=head[x]; i!=-1; i=Node[i].next) { node e = Node[i]; if(d[e.v] > d[x] + e.w) { d[e.v] = d[x] + e.w; Q.push(e.v); vis[e.v] = 1; if(++ans[e.v] > n) return 1; } } } return 0; } int main() { int T; scanf("%d",&T); while(T--) { mem(G,0); mem(ans,0); mem(head,-1); mem(Node,0); int ok = 0; scanf("%d%d%d",&n,&m,&p); int cnt = 0; for(int i=0; i<m; ++i) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w,cnt++); add(v,u,w,cnt++); } for(int i=0; i<p; ++i) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,-w,cnt++); } if(spfa(1)) printf("YES\n"); else printf("NO\n"); } return 0; }
原文地址:https://www.cnblogs.com/WTSRUVF/p/9145841.html
时间: 2024-10-08 06:59:46