zoukankan      html  css  js  c++  java
  • AcWing 904. 虫洞 spfa 图论

    地址 https://www.acwing.com/problem/content/description/906/

    农夫约翰在巡视他的众多农场时,发现了很多令人惊叹的虫洞。
    
    虫洞非常奇特,它可以看作是一条 单向 路径,
    通过它可以使你回到过去的某个时刻(相对于你进入虫洞之前)。
    
    农夫约翰的每个农场中包含N片田地,M条路径(双向)以及W个虫洞。
    
    现在农夫约翰希望能够从农场中的某片田地出发,经过一些路径和虫洞回到过去,
    并在他的出发时刻之前赶到他的出发地。
    
    他希望能够看到出发之前的自己。
    
    请你判断一下约翰能否做到这一点。
    
    下面我们将给你提供约翰拥有的农场数量F,以及每个农场的完整信息。
    
    已知走过任何一条路径所花费的时间都不超过10000秒,
    任何虫洞将他带回的时间都不会超过10000秒。
    
    输入格式
    第一行包含整数F,表示约翰共有F个农场。
    
    对于每个农场,第一行包含三个整数N,M,W。
    
    接下来M行,每行包含三个整数S,E,T,表示田地S和E之间存在一条路径,
    经过这条路径所花的时间为T。
    
    再接下来W行,每行包含三个整数S,E,T,表示存在一条从田地S走到田地E的虫洞,
    走过这条虫洞,可以回到T秒之间。
    
    输出格式
    输出共F行,每行输出一个结果。
    
    如果约翰能够在出发时刻之前回到出发地,则输出“YES”,否则输出“NO”。
    
    数据范围
    1≤F≤5
    1≤N≤500,
    1≤M≤2500,
    1≤W≤200,
    1≤T≤10000,
    1≤S,E≤N
    输入样例:
    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
    输出样例:
    NO
    YES

    解答

    由于虫洞是回到之前 所以可以看做是田地为点的负权值边。
    田地之间是双向边。
    只要检测到图中存在负环,那么就可以无限穿越到之前的时间,而由于田地点之间是双向边,所以肯定能到达任意一个田地(也包括起点)。所以本题目就是判断图中是否存在负环。
    是一个spfa判断负环的模板题目

    // 1231234.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #include <iostream>
    #include <queue>
    #include <vector>
    #include <memory.h>
    
    
    using namespace std;
    
    int loop;
    const int N = 510;
    int n, m, w;
    vector<pair<int, int>> g[N];
    bool st[N];
    int dist[N];
    int cnt[N];
    
    bool spfa()
    {
        queue<int> q;
        for (int i = 1; i <= n; i++) {
            st[i] = true;
            q.push(i);
        }
    
        while (q.size()) {
            int t = q.front();
            q.pop();
    
            st[t] = false;
    
            for (int i = 0; i < g[t].size(); i++) {
                int j = g[t][i].first;
                int w = g[t][i].second;
                if (dist[j] > dist[t] + w) {
                    dist[j] = dist[t] + w;
                    cnt[j] = cnt[t] + 1;
    
                    if (cnt[j] >= n) return true;
                    if (!st[j]) {
                        q.push(j);
                        st[j] = true;
                    }
                }
            }
    
        }
    
        return false;
    }
    
    int main()
    {
        cin >> loop;
    
        while (loop--) {
            //多样例 初始化
            memset(st, 0, sizeof st);
            memset(dist, 0, sizeof dist);
            memset(cnt, 0, sizeof cnt);
            for (int i = 0; i < N; i++) g[i].clear();
            cin >> n >> m >> w;
            for (int i = 0; i < m; i++) {
                int a, b, c;
                cin >> a >> b >> c;
                g[a].push_back({ b,c });
                g[b].push_back({ a,c });
            }
            for (int i = 0; i < w; i++) {
                int a, b, c;
                cin >> a >> b >> c;
                g[a].push_back({ b,-c });
            }
            if (spfa()) cout << "YES" << endl;
            else cout << "NO" << endl;
        }
    
        return 0;
    }
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    韩式英语
    Daily dictation 听课笔记
    words with same pronunciation
    you will need to restart eclipse for the changes to take effect. would you like to restart now?
    glottal stop(britain fountain mountain)
    education 的发音
    第一次用Matlab 的lamada语句
    SVN的switch命令
    String的split
    SVN模型仓库中的资源从一个地方移动到另一个地方的办法(很久才解决)
  • 原文地址:https://www.cnblogs.com/itdef/p/13197860.html
Copyright © 2011-2022 走看看