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驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    329. Longest Increasing Path in a Matrix
    2、evaluate-reverse-polish-notation
    1、minimum-depth-of-binary-tree
    2、替换空格
    C风格字符串和C++string对象的相互转化
    1、二维数组中的查找
    8、sort排序中比较函数的几种应用方式
    1131(★、※)Subway Map
    7、(★、※)判断一个序列是否是二叉查找树的后序、前序遍历序列
    041219~051219流水账
  • 原文地址:https://www.cnblogs.com/itdef/p/13197860.html
Copyright © 2011-2022 走看看