P2850-虫洞Wormholes-bellman_ford找负环

题目描述

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.

John在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。John的每个农场有M条小路(无向边)连接着N (从1..N标号)块地,并有W个虫洞。其中1<=N<=500,1<=M<=2500,1<=W<=200。 现在John想借助这些虫洞来回到过去(出发时刻之前),请你告诉他能办到吗。 John将向你提供F(1<=F<=5)个农场的地图。没有小路会耗费你超过10000秒的时间,当然也没有虫洞回帮你回到超过10000秒以前。

输入输出格式

输入格式:

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.

输出格式:

Lines 1..F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

输入输出样例

输入样例#1: 

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

输出样例#1: 

NO
YES

说明

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.

思路:找是否有负环,负环可以一直循环到将自己放回过去的时间,

田埂是双向路径,双向建图,虫洞是单向的,但是要赋予负的时间,然后枚举每个点判断能否产生负环,

条件为:d[en]>d[st]+w;如果存在则能产生负环(d[i]为到i点为止,所产生的总值,如果到下一点为止产生的总值大于前面的所有点值加上下一点本身的权值,则重新刷新)

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <iostream>
#define INF 777777
using namespace std;

struct node
{
    int st,en,w;
}a[5500];

int d[5500];
int n,e,m,w;

int bellman_ford()
{
    for(int i=1;i<=n;i++)
        d[i]=INF;
    d[1]=0;

    for(int i=1;i<n;i++)
    {
        int flag=1;
        for(int j=0;j<e;j++)
        {
            int st=a[j].st;
            int en=a[j].en;
            int w=a[j].w;

            if(d[en]>d[st]+w)
            {
                d[en]=d[st]+w;
                flag=0;
            }
        }
        if(flag)
            return 0;
    }
    for(int i=0;i<e;i++)
    {
        if(d[a[i].en]>d[a[i].st]+a[i].w)
            return 1;
    }
    return 0;
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>w;
        e=0;
        int st,en,wi;
        for(int i=1;i<=m;i++)
        {
            cin>>st>>en>>wi;

            a[e].st=st;a[e].en=en;a[e].w=wi;e++;
            a[e].st=en;a[e].en=st;a[e].w=wi;e++;
        }
        for(int i=1;i<=w;i++)
        {
            cin>>st>>en>>wi;

            a[e].st=st;a[e].en=en;a[e].w=-wi;e++;
        }
        if(bellman_ford()!=0)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wentong_Xu/article/details/81239081