zoukankan      html  css  js  c++  java
  • POJ 3259 bell_man求负环 || SPFA(bell_man模板+SPFA)

    题目:https://vjudge.net/problem/POJ-3259

    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.
     
     
    题意:
    给你三个数n,m,w,分别表示有n个农场,m条路,w个黑洞,接下来m行分别有三个数s,e,val表示s到e有一条权值为val 的边,接下来的w行每行有三个数s,e,val表示s到e有一条权值为0-val的边,因为黑洞可以回到过去,所以其权值为负。现在问你给你这些点,求每组数据是否存在一条回路能使时间倒退。
     
     
    思路:求负环就行      bell——man模板题            有SPFA的优化版              代码来自https://blog.csdn.net/iceiceicpc/article/details/51986857
              因为自己的代码死都过不了的那种,,查错到失望
     
    代码:
      //    bell_man模板
    
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<algorithm>
    #include<map>
    #define maxn 200005
    using namespace std;
    const int maxv=500+5;
    const int maxe=6000+5;
    const int INF=0x3f3f3f3f;
    struct proc
    {
        int s,e,t;    //起点  终点  边权
    }edge[maxe];
    int n,m,w,dis[maxv];
    int cnt;
    void addEdge(int s,int e,int t)   //建立图
    {
        edge[cnt].s=s;
        edge[cnt].e=e;
        edge[cnt++].t=t;
    }
    int bell_man()
    {
        bool flag;
        //松弛
        for(int i=1;i<=n;i++)
        {
            flag=false;
            for(int j=1;j<=cnt;j++)
            {
                if(dis[edge[j].e]>dis[edge[j].s]+edge[j].t)
                {
                    dis[edge[j].e]=dis[edge[j].s]+edge[j].t;
                    flag=true;
                }
            }
            if(!flag) break;
        }
        //寻找负环,判断条件是负环可以无限松弛。
        for(int i=1;i<=cnt;i++)
        {
            if(dis[edge[i].e]>dis[edge[i].s]+edge[i].t)
            {
                return true;
            }
        }
        return false;
    }
    
    int main()
    {
        int s,e,v;
        int cas;
        scanf("%d",&cas);
        while(cas--)
        {
            memset(dis,INF,sizeof(dis));
            cnt=1;
            scanf("%d %d %d",&n,&m,&w);
            for(int i=1;i<=m;i++)
            {
                scanf("%d %d %d",&s,&e,&v);
                addEdge(s,e,v);
                addEdge(e,s,v);
            }
            for(int i=1;i<=w;i++)
            {
                scanf("%d %d %d",&s,&e,&v);
                addEdge(s,e,0-v);
            }
            int ans=bell_man();
            if(ans) printf("YES
    ");
            else printf("NO
    ");
        }
        return 0;
    }
    
          //   SPFA优化模板
    //
    //#include <iostream>
    //#include <cstdio>
    //#include <cstring>
    //#include <algorithm>
    //#include <queue>
    //
    //using namespace std;
    //const int maxn=500+5;
    //const int maxe=6000+5;
    //const int INF=0x7fffffff;
    //
    //struct proc
    //{
    //    int v,w;
    //    int next;
    //};
    //
    //proc edge[maxe];
    //int dis[maxn],vis[maxn],f,n,m,w,head[maxe];
    //int cnt[maxn];
    //
    //int k;
    //void addEdge(int u,int v,int w)
    //{
    //    edge[k].v=v;
    //    edge[k].w=w;
    //    edge[k].next=head[u];
    //    head[u]=k++;
    //}
    //
    //bool spfa()
    //{
    //    for(int i=0;i<=n;i++)
    //    {
    //        dis[i]=INF;
    //    }
    //    memset(cnt,0,sizeof(cnt));
    //    memset(vis,0,sizeof(vis));
    //    queue<int> q;
    //    vis[1]=1;
    //    dis[1]=0;
    //    cnt[1]=1;
    //    q.push(1);
    //    while(!q.empty())
    //    {
    //        int cur=q.front();
    //        q.pop();
    //        vis[cur]=false;
    //        for(int i=head[cur];i+1;i=edge[i].next)
    //        {
    //            int id=edge[i].v;
    //            if(dis[cur]+edge[i].w<dis[id])
    //            {
    //                dis[id]=dis[cur]+edge[i].w;
    //                if(!vis[id])
    //                {
    //                    cnt[id]++;
    //                    if(cnt[cur]>=n)
    //                        return false;
    //                    vis[id]=true;
    //                    q.push(id);
    //                }
    //            }
    //        }
    //    }
    //    return true;
    //}
    //
    //int main()
    //{
    //    while(~scanf("%d",&f))
    //    {
    //        while(f--)
    //        {
    //            scanf("%d %d %d",&n,&m,&w);
    //            k=0;
    //            memset(head,-1,sizeof(head));
    //            int s,e,val;
    //            for(int i=0;i<m;i++)
    //            {
    //                scanf("%d %d %d",&s,&e,&val);
    //                addEdge(s,e,val);
    //                addEdge(e,s,val);
    //            }
    //            for(int i=0;i<w;i++)
    //            {
    //                scanf("%d %d %d",&s,&e,&val);
    //                addEdge(s,e,0-val);
    //            }
    //            if(spfa()) printf("NO
    ");
    //            else printf("YES
    ");
    //        }
    //    }
    //}
     SPFA的详解:   https://blog.csdn.net/acm_1361677193/article/details/48211319
     
     
  • 相关阅读:
    LCA问题
    CSP2019 J组 游记
    树的直径
    动态规划-背包问题
    Diworth定理
    扫描线算法
    线段树2:区间乘法实现
    线段树1:区间查询和区间加法
    Sys.WebForms.PageRequestManagerParserErrorException: 常见的原因是:通过调用Response.Write()修改相应时,将启用响应筛选器、HttpModules或服务器追踪
    10 套华丽的 CSS3 按钮推荐
  • 原文地址:https://www.cnblogs.com/huangzzz/p/8847716.html
Copyright © 2011-2022 走看看