题意:FJ发现了许多虫洞,通过虫洞可以使时光倒流,通过普通的路时间增加,给出一张有向带负权图,问FJ能不能从某一点出发回到这一点时回到了过去。
解法:Bellman-Ford判负环。先做n-1次松弛,得到最多用n-1条边时从源点到每一个点的最短路径,如果再做一次松弛还可以减少路径长度,说明有负环。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define LL long long using namespace std; struct node { int u, v, value; node(int u, int v, int value) : u(u), v(v), value(value) {} node() {} } edge[5300]; int n, m, w, cnt; int dis[505]; const int inf = 0x3f3f3f3f; bool BellmanFord() { memset(dis, inf, sizeof dis); dis[1] = 0; for(int i = 0; i < n - 1; i++) for(int j = 0; j < cnt; j++) dis[edge[j].v] = min(dis[edge[j].u] + edge[j].value, dis[edge[j].v]); for(int i = 0; i < cnt; i++) { if(dis[edge[i].v] > dis[edge[i].u] + edge[i].value) return 1; } return 0; } int main() { int T; while(~scanf("%d", &T)) { while(T--) { cnt = 0; scanf("%d%d%d", &n, &m, &w); for(int i = 0; i < m; i++) { int u, v, value; scanf("%d%d%d", &u, &v, &value); edge[cnt++] = node(u, v, value); edge[cnt++] = node(v, u, value); } for(int i = 0; i < w; i++) { int u, v, value; scanf("%d%d%d", &u, &v, &value); edge[cnt++] = node(u, v, -value); } if(BellmanFord()) puts("YES"); else puts("NO"); } } return 0; }
原文:http://www.cnblogs.com/Apro/p/4604567.html