zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    hdu2138(求素数)
    hdu2104
    poj1664(放苹果)
    数塔问题给你有哪些启示?
    汉诺塔问题(1)
    算法的力量(转李开复)
    最长子序列问题之系列一
    forward和redirect的区别
    group by 和having
    java中的多态三要素是什么?
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2644921.html
Copyright © 2011-2022 走看看