POJ 3255 Wormholes(最短路最负环)

Wormholes
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 20639   Accepted: 7342

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

 
 
 
 
这题一方面是找负环。。其实环需要判断起点和负环是不是连通的。因为要求是回到起点。。有可能有负环,但是回不去起点。。。
暂时还没有好的办法判断负环和起点相连,或者起点是负环的一部分。。。路过的大牛知道的话指点下。
 
但是本题数据都是连通的,直接SPFA或者BF做
 
Bellman_Ford
/*

POJ 3259

就是判断负环回路。

用SPFA和BellmanFord都可以



但是一直想不通的是题目要求是要回到出发点,

有负环可能回不去啊。。。。数据弱爆了。。。Orz



*/

// G++ 732K 94ms

#include<stdio.h>

#include<iostream>

#include<algorithm>

#include<iostream>

using namespace std;

const int MAXN=550;

const int MAXE=5050;

const int INF=0x3f3f3f3f;

int dist[MAXN];



int edge[MAXE][3];

int tol;



bool bellman(int start,int n)

{

    for(int i=1;i<=n;i++)dist[i]=INF;

    dist[start]=0;

    for(int i=1;i<n;i++)

    {

        bool flag=false;

        for(int j=0;j<tol;j++)

        {

            if(dist[edge[j][1]]>dist[edge[j][0]]+edge[j][2])

            {

                dist[edge[j][1]]=dist[edge[j][0]]+edge[j][2];

                flag=true;

            }

        }

        if(!flag)return false;//没有负环

    }



    for(int j=0;j<tol;j++)

       if(dist[edge[j][1]]>dist[edge[j][0]]+edge[j][2])

          return true;

    return false;

}

int main()

{

    int n,M,W;

    int a,b,c;

    int T;

    scanf("%d",&T);

    while(T--)

    {

        scanf("%d%d%d",&n,&M,&W);

        tol=0;

        while(M--)

        {

            scanf("%d%d%d",&a,&b,&c);

            edge[tol][0]=a;

            edge[tol][1]=b;

            edge[tol][2]=c;

            tol++;

            edge[tol][0]=b;

            edge[tol][1]=a;

            edge[tol][2]=c;

            tol++;

        }

        while(W--)

        {

            scanf("%d%d%d",&a,&b,&c);

            edge[tol][0]=a;

            edge[tol][1]=b;

            edge[tol][2]=-c;

            tol++;

        }

        if(bellman(1,n))printf("YES\n");

        else printf("NO\n");

    }

    return 0;

}

 

 

SPFA:

/*

POJ 3259



SPFA判断负环

*/



//G++ 756K 157ms

#include<stdio.h>

#include<iostream>

#include<string.h>

#include<algorithm>

using namespace std;

const int MAXN=550;

const int MAXE=5050;//这个5000会RE

const int INF=0x3f3f3f3f;

int head[MAXN];

int dist[MAXN];

int cnt[MAXN];

int que[MAXN];

bool vis[MAXN];



struct edge

{

    int to;

    int next;

    int v;

}edge[MAXE];

int tol;



void add(int a,int b,int c)

{

    edge[tol].to=b;

    edge[tol].v=c;

    edge[tol].next=head[a];

    head[a]=tol++;

}



bool SPFA(int start,int n)

{

    int front=0,rear=0;

    for(int v=1;v<=n;v++)

    {

        if(v==start)

        {

            dist[v]=0;

            que[rear++]=v;

            vis[v]=true;

            cnt[v]=1;

        }

        else

        {

            dist[v]=INF;

            vis[v]=false;

            cnt[v]=0;

        }

    }

    while(front!=rear)

    {

        int u=que[front++];

        vis[u]=false;

        if(front>=MAXN)front=0;

        for(int i=head[u];i!=-1;i=edge[i].next)

        {

            int v=edge[i].to;

            if(dist[v]>dist[u]+edge[i].v)

            {

                dist[v]=dist[u]+edge[i].v;

                if(!vis[v])

                {

                    vis[v]=true;

                    que[rear++]=v;

                    if(rear>=MAXN)rear=0;

                    if(++cnt[v]>n)return true;

                }

            }

        }

    }

    return false;

}

int main()

{

   // freopen("in.txt","r",stdin);

   // freopen("out.txt","w",stdout);

    int n,M,W;

    int a,b,c;

    int T;

    scanf("%d",&T);

    while(T--)

    {

        scanf("%d%d%d",&n,&M,&W);

        tol=0;

        memset(head,-1,sizeof(head));//这个不能忘记!!!

        while(M--)

        {

            scanf("%d%d%d",&a,&b,&c);

            add(a,b,c);

            add(b,a,c);

        }

        while(W--)

        {

            scanf("%d%d%d",&a,&b,&c);

            add(a,b,-c);

        }

        if(SPFA(1,n))printf("YES\n");

        else printf("NO\n");

    }

    return 0;

}

 

你可能感兴趣的:(orm)