zoukankan      html  css  js  c++  java
  • [kuangbin带你飞]专题四 最短路练习 F

    F - Wormholes

    题目链接:https://vjudge.net/contest/66569#problem/F

    题目:

    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(1≤N≤500)个农场被编号为1..N,之间有M(1≤M≤2500)条路径,W(1≤W≤200)个虫洞。FJ作为一个狂热的时间旅行的爱好者,他要做到以下几点:开始在一个区域,通过一些路径和虫洞旅行,他要回到最开时出发的那个区域出发前的时间。也许他就能遇到自己了:)。为了帮助FJ找出这是否是可以或不可以,他会为你提供F个农场的完整的映射到(1≤F≤5)。所有的路径所花时间都不大于10000秒,所有的虫洞都不大于万秒的时间回溯。

    Input

    第1行:一个整数F表示接下来会有F个农场说明。 每个农场第一行:分别是三个空格隔开的整数:N,M和W 第2行到M+1行:三个空格分开的数字(S,E,T)描述,分别为:需要T秒走过S和E之间的双向路径。两个区域可能由一个以上的路径来连接。 第M +2到M+ W+1行:三个空格分开的数字(S,E,T)描述虫洞,描述单向路径,S到E且回溯T秒。

    Output

    F行,每行代表一个农场 每个农场单独的一行,” YES”表示能满足要求,”NO”表示不能满足要求。
     
    思路:
    套判断负环的模板即可
    先给出我一开始用的spfa算法如下,用时235s:
    //
    // Created by hanyu on 2019/7/19.
    //
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int maxn=2e5+7;
    #define MAX 0x3f3f3f3f
    int book[maxn],cnt[maxn],d[maxn],head[maxn];
    int n,m,w;
    int pos;
    struct Node{
        int s;
        int e;
        int t;
    }node[maxn];
    void add(int s,int e,int t)
    {
        node[pos].s=e;
        node[pos].e=t;
        node[pos].t=head[s];
        head[s]=pos++;
    }
    bool spfa(int start)
    {
    
        queue<int>qu;
        qu.push(start);
        book[start]=1;
        d[start]=0;
        while(!qu.empty())
        {
            int now=qu.front();
            qu.pop();
            book[now]=0;
            for(int i=head[now];i!=-1;i=node[i].t)
            {
                int ss=node[i].s;
                int ee=node[i].e;
                if(d[ss]>d[now]+ee)
                {
                    d[ss]=d[now]+ee;
                    if(!book[ss])
                    {
                        qu.push(ss);
                        book[ss]=1;
                        cnt[ss]++;
                        if(cnt[ss]>=n)
                        return true;//判断负环
                    }
                }
            }
        }
        return false;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            memset(book,0,sizeof(book));
            memset(cnt,0,sizeof(cnt));
            memset(d,MAX,sizeof(d));
            memset(head,-1,sizeof(head));
            memset(node,0,sizeof(node));
            scanf("%d%d%d",&n,&m,&w);
            int s,e,t;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%d",&s,&e,&t);
                add(s,e,t);
                add(e,s,t);
            }
            for(int i=1;i<=w;i++)
            {
                scanf("%d%d%d",&s,&e,&t);
                add(s,e,-t);
            }
            cnt[1]=1;
            pos=0;
            if(spfa(1))
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }

    然后学习了优化版的Bellmanford算法,发现速度更快,用时79s

    //
    // Created by hanyu on 2019/7/20.
    //
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int maxn=6005;
    #define MAX 0x3f3f3f3f
    int n,m,w;
    
    int pos;
    int d[maxn];
    
    struct Node{
        int u,v,w;
    }node[maxn];
    void add(int u,int v,int w)
    {
        node[++pos].u=u;
        node[pos].v=v;
        node[pos].w=w;
    }
    bool bell(){
    
        memset(d,MAX,sizeof(d));
        d[1]=0;
        int flag=0;
        for(int i=1;i<=n;i++)
        {
           flag=0;
           for(int j=1;j<=pos;j++)
           {
               if(d[ node[j].v]>d[node[j].u]+node[j].w)
               {
                   d[ node[j].v]=d[node[j].u]+node[j].w;
                   flag=1;
               }
           }
           if(flag==0)
               return false;
        }
        flag=0;
        for(int i=1;i<=pos;i++)
        {
            if(d[node[i].v]>d[node[i].u]+node[i].w)
                return 1;
        }
        return 0;
    }
    int main()
    {
        int T;
        int a,b,c;
        scanf("%d",&T);
        while(T--)
        {
            pos=0;
            scanf("%d%d%d
    ",&n,&m,&w);
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,c);
                add(b,a,c);
            }
            for(int i=1;i<=w;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,-c);
            }
            if(bell())
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
  • 相关阅读:
    三国演义中的十大谎言 VS 程序员十大口头禅
    Node.js 的单线程事件驱动模型和内置的线程池模型
    为了让医院把医护还给患者,他们用了这个…
    华为云数据库内核专家为您揭秘:GaussDB(for MySQL)并行查询有多快?
    brew
    Python
    Python
    Python
    AtCoder Beginner Contest 215 (个人题解 A~F)
    AcWing 第 13 场周赛  补题记录
  • 原文地址:https://www.cnblogs.com/Vampire6/p/11216351.html
Copyright © 2011-2022 走看看