POJ 3259 Wormholes

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..NM (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, FF farm descriptions follow. 
Line 1 of each farm: Three space-separated integers respectively: NM, and W
Lines 2.. M+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: a bidirectional path between S and E that requires Tseconds to traverse. Two fields might be connected by more than one path. 
Lines M+2.. MW+1 of each farm: Three space-separated numbers ( SET) 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.
 
题意:有n个田野,m条路径,w个时光隧道(非常神奇的是它可以让FJ从田野a直接到田野b,并且回到c秒之前),现在告诉你路径和时光隧道,求出FJ能否见到另一个还未出发的自己。(如果能够利用时光隧道回到出发点,并且到达时光隧道的时间比时光隧道穿梭的时间要小,就能看见自己了)
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;

const int N=510;
const int INF=0x3f3f3f3f;

int G[N][N], dist[N], cou[N], vis[N], n; ///cou数组保存该点被遍历的次数

void Init()
{
    int i, j;

    for (i = 1; i <= n; i++)
    {
        dist[i] = INF;
        cou[i] = vis[i] = 0;
        for (j = 1; j <= n; j++)
            G[i][j] = INF;
        G[i][i] = 0;
    }
}

int Spfa()
{
    int i, v;
    queue<int>Q;

    Q.push(1);
    dist[1] = 0;
    cou[1]++;

    while (!Q.empty())
    {
        v = Q.front(); Q.pop();

        for (i = 1; i <= n; i++)
        {
            if (dist[i] > G[v][i]+dist[v])
            {
                dist[i] = G[v][i]+dist[v];

                if (!vis[i])
                {
                    Q.push(i);
                    vis[i] = 1;
                    cou[i]++;
                    if (cou[i] >= n && dist[i] < 0)
                        return 1; ///如果存在回路并且并且到达时光隧道的时间比时光隧道穿梭的时间要小
                }
            }
        }

        vis[v] = 0;
    }

    return 0;
}

int main ()
{
    int T, a, b, c, m, w, ans;

    scanf("%d", &T);

    while (T--)
    {
        scanf("%d%d%d", &n, &m, &w);

        Init();

        while (m--)
        {
            scanf("%d%d%d", &a, &b, &c);
            G[a][b] = min(G[a][b], c);
            G[b][a] = G[a][b];
        }
        while (w--)
        {
            scanf("%d%d%d", &a, &b, &c);
            G[a][b] = -c; ///因为时光隧道可以回到c秒前,直接赋值为-c就行了
        }

        ans = Spfa();

        if (ans) printf("YES
");
        else printf("NO
");
    }

    return 0;
}
原文地址:https://www.cnblogs.com/syhandll/p/4812606.html