http://poj.org/problem?id=3259
这道题的意思就是 考虑从任意一个点出发 经过任意回路 (普通道路是双向 虫洞是单向并且是负边)
问回到出发点时 时间是不是小于 出发时的时间
最开始直接想求所有点 到自己点的最短路
做着做着发现 如果可以的话 那不是没有最短路 因为每次都会更新---->>那不就是负圈
--->>那不就是 判断是否存在负圈
-->>所以直接用Bellman_ford的性质 判断负圈即可
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define INF 0x3f3f3f3f 5 #define MAXV 507 6 #define MAXE 5800 7 using namespace std; 8 9 struct Edge 10 { 11 int to, cost, next;//向前星 遍历边 然后松弛用向前星同样可以遍历边 只不过按起点而已 12 }edge[MAXE]; 13 14 int head[MAXV]; 15 int num = 0; 16 17 void Add(int from, int to, int c) 18 { 19 edge[num].cost = c; 20 edge[num].to = to; 21 edge[num].next = head[from]; 22 head[from] = num++; 23 } 24 25 int dist[MAXV]; 26 bool bellman_ford(int n)//顶点数 27 { 28 fill(dist, dist+n+3, 0);//全部变为0 查负圈 29 for (int k = 0; k < n; k++)//不存在负圈 至多循环n-1次 按这个性质可以判断是否含有负圈 30 for (int i = 1; i <= n; i++) 31 { 32 int t = head[i]; 33 while (t != -1) 34 { 35 Edge e = edge[t]; 36 if (dist[e.to] > dist[i] + e.cost) 37 { 38 dist[e.to] = dist[i] + e.cost; 39 if (k == n-1) return true;//如果第n-1次仍然更新 40 } 41 t = e.next; 42 } 43 } 44 return false; 45 } 46 int main() 47 { 48 int F; 49 freopen("in.txt", "r", stdin); 50 scanf("%d",&F); 51 while(F--) 52 { 53 int N, M, W; 54 num = 0; 55 memset(edge, -1, sizeof(edge)); 56 memset(head, -1, sizeof(head)); 57 scanf("%d%d%d", &N, &M, &W); 58 for (int i = 0;i < M; i++) 59 { 60 int from, to, cost; 61 scanf("%d%d%d", &from, &to, &cost); 62 Add(from, to, cost); 63 Add(to, from, cost);//双向边 64 } 65 for (int i = 0; i < W; i++) 66 { 67 int from, to, cost; 68 scanf("%d%d%d", &from, &to, &cost); 69 Add(from, to, -cost); 70 } 71 if (bellman_ford(N)) cout << "YES" << endl; 72 else cout << "NO" << endl; 73 } 74 }