链接:http://poj.org/problem?id=3259
Description
While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ‘s farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..N, M (1 ≤ M ≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.
As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .
To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.
Input
Output
Sample Input
2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8
Sample Output
NO
YES
Hint
题目大意:
有一个农场,里面有一些奇怪的单向虫洞,通过虫洞的入口到出口可以让时间倒退,农场主想知道他是否能够通过农场中的路和虫洞走回出发点,并且使时间倒退,给出农场中的N块地, M条路以及W个虫洞;
分析:
由题意可以看出实际目标位寻找负值回路,所以可以使用Bellman - Ford或者SPFA判断图中是否存在负权回路即可;
代码:
(Bellman - Ford):
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #define MAXN 505 #define RST(N)memset(N, 0, sizeof(N)) using namespace std; typedef struct Edge_ { int u, v, t; }Edge; Edge edge[6005]; int res[MAXN]; //存储源点到每个顶点的最短距离值; int cas, n, m, w, s, e, t; void READ_DATA() { scanf("%d %d %d", &n, &m, &w); for(int i=0; i<m; i++) { scanf("%d %d %d", &s, &e, &t); edge[i].u = s, edge[i].v = e, edge[i].t = t; edge[i+m].u = e, edge[i+m].v = s, edge[i+m].t = t; } for(int i=0; i<w; i++) { scanf("%d %d %d", &s, &e, &t); edge[i+2*m].u = s, edge[i+2*m].v = e, edge[i+2*m].t = -t; } } bool Bellman(int n, int m, int src) //判断是否有负环; { memset(res, 0x1f, sizeof(res)); //初始化每个顶点的最短距离为无穷大; res[src] = 0; //源点的距离为0; for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(res[edge[j].u] + edge[j].t < res[edge[j].v]) res[edge[j].v] = res[edge[j].u] + edge[j].t; } } for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(res[edge[j].u] + edge[j].t < res[edge[j].v]) return true; } } return false; } int main() { scanf("%d", &cas); while(cas--) { READ_DATA(); if(Bellman(n, 2*m+w, 1)) puts("YES"); else puts("NO"); } return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #define MAXN 505 #define RST(N)memset(N, 0, sizeof(N)) using namespace std; int res[MAXN]; //存储源点到每个顶点的最短距离值; int map[MAXN][MAXN]; int cnt[MAXN]; //每个点入队次数; int que[MAXN*MAXN]; //队列; bool In_que[MAXN]; //标记一个点是否出现在队列中; int front, rear, cas; //队首,队尾,测试数据个数; int n, m, w, s, e, t; void READ_DATA() { scanf("%d %d %d", &n, &m, &w); memset(map, 0x1f, sizeof(map)); for(int i=0; i<m; i++) { scanf("%d %d %d", &s, &e, &t); map[s][e] = map[e][s] = map[s][e] > t ? t : map[s][e]; } for(int i=0; i<w; i++) { scanf("%d %d %d", &s, &e, &t); map[s][e] = map[s][e] < -t ? map[s][e] : -t; } } bool SPFA(int n, int src) { RST(cnt), RST(In_que); front = rear = 0; que[++rear] = src; cnt[src]++; memset(res, 0x1f, sizeof(res)); res[src] = 0; while(front < rear) { int current = que[++front]; In_que[current] = 0; for(int i=1; i<=n; i++) { if(res[current] + map[current][i] < res[i]) { res[i] = res[current] + map[current][i]; if(!In_que[i]) { que[++rear] = i, cnt[i]++; if(cnt[i] >= n) return true; } } } } return false; } int main() { scanf("%d", &cas); while(cas--) { READ_DATA(); if(SPFA(n, 1)) puts("YES"); else puts("NO"); } return 0; }
POJ 3259 Wormholes (图论---最短路 Bellman-Ford || SPFA),布布扣,bubuko.com
POJ 3259 Wormholes (图论---最短路 Bellman-Ford || SPFA)
原文:http://blog.csdn.net/keshacookie/article/details/27183339