Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 60687 | Accepted: 22655 |
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
Line 1: A single integer,
F.
F
farm descriptions follow.
Line 1 of each farm: Three space-separated integers respectively:
N,
M, and
W
Lines 2..
M+1 of each farm: Three space-separated numbers (
S,
E,
T) that describe, respectively: a bidirectional path between
S
and
E
that requires
T
seconds to traverse. Two fields might be connected by more than one path.
Lines
M+2..
M+
W+1 of each farm: Three space-separated numbers (
S,
E,
T) that describe, respectively: A one way path from
S
to
E
that also moves the traveler back
T
seconds.
Output
Lines 1..
F: For each farm, output “YES” if FJ can achieve his goal, otherwise output “NO” (do not include the quotes).
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
For farm 1, FJ cannot travel back in time.
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.
Source
问题链接:POJ3259 HYSBZ1715(BZOJ1715) Wormholes
问题描述:(略)
问题分析:
这个问题采用Bellman ford算法来解。
解法一采用邻接矩阵存储图,顶点数为n,其算法复杂度为O(n^3)。
解法二采用邻接表存储图,顶点数为n,边数为e,其算法复杂度为O(n*e)。
程序说明:
采用解法一时,使用函数min(),程序会超时,有点奇怪。代码写法是:
grid[i][j] = min(grid[i][j], grid[i][k] + grid[k][j]);
参考链接:(略)
AC的C++语言程序(解法二)如下:
/* POJ3259 HYSBZ1715(BZOJ1715) Wormholes */
#include <iostream>
#include <stdio.h>
using namespace std;
const int INF = 1 << 30;
const int N = 500;
const int M = 2500;
const int W = 200;
int n, m, w, cnt;
int dist[N + 1];
struct Edge {
int src, dest, cost;
} edges[M * 2 + W];
bool bellman_ford(int v) {
for( int i = 1; i <= n; i++)
dist[i] = INF;
dist[v] = 0;
for( int k = 1; k < n; k++) { // 经过不超过k条边
for( int i = 0; i < cnt; i++) {
int s = edges[i].src;
int e = edges[i].dest;
if( dist[s] + edges[i].cost < dist[e])
dist[e] = dist[s] + edges[i].cost;
}
}
for( int i = 0; i < cnt; i++) {
int s = edges[i].src;
int e = edges[i].dest;
if( dist[s] + edges[i].cost < dist[e])
return true;
}
return false;
}
int main()
{
int f;
scanf("%d", &f);
while(f--) {
scanf("%d%d%d", &n, &m, &w);
int s, e, t;
cnt = 0;
for(int i = 0; i < m; i++) {
scanf("%d%d%d", &s, &e, &t);
edges[cnt].src = s;
edges[cnt].dest = e;
edges[cnt++].cost = t;
edges[cnt].src = e;
edges[cnt].dest = s;
edges[cnt++].cost = t;
}
for(int i = 0; i < w; i++) {
scanf("%d%d%d", &s, &e, &t);
edges[cnt].src = s;
edges[cnt].dest = e;
edges[cnt++].cost = -t;
}
// 输出结果
printf("%s\n", bellman_ford(1) ? "YES" : "NO");
}
return 0;
}
AC的C++语言程序(解法一)如下:
/* POJ3259 HYSBZ1715(BZOJ1715) Wormholes */
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int INF = 0x3f;
const int N = 500;
int n, m, k, grid[N + 1][N + 1];
bool bellman_floyd()
{
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++) {
for(int j = 1; j <=n; j++) {
int t = grid[i][k] + grid[k][j];
if(grid[i][j] > t)
grid[i][j] = t;
}
if(grid[i][i] < 0)
return true;
}
return false;
}
int main()
{
int f;
scanf("%d", &f);
while(f--) {
scanf("%d%d%d", &n, &m, &k);
memset(grid, INF, sizeof(grid));
for(int i = 1; i <= n; i++)
grid[i][i] = 0;
int a, b, c;
for(int i = 1; i <= m; i++) {
scanf("%d%d%d", &a, &b, &c);
if(c < grid[a][b])
grid[a][b] = grid[b][a] = c;
}
for(int i = 1; i <= k; i++) {
scanf("%d%d%d", &a, &b, &c);
grid[a][b] = -c;
}
// 输出结果
printf("%s\n", bellman_floyd() ? "YES" : "NO");
}
return 0;
}