• 题解【洛谷P2850】[USACO06DEC]虫洞Wormholes


    题面

    SPFA 判负环裸题。

    SPFA 判断负环主要有 (2) 种方法:

    1. 判断每个点的出队次数是否 大于等于 (n)
    2. 判断每个点最短路径上点的个数是否 大于等于 (n)

    这两种方法都很好证明。我个人比较推荐使用第二种方法。

    因此,我们只要在 SPFA 的过程中记录一下每个点上最短路径上点的个数。

    因为我们一开始将所有的点放进了队列中,所以 (dist) 数组就要初始化成 (0)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 503, M = 5203;
    
    int n, m, f, w;
    int tot, head[N], ver[M], edge[M], nxt[M];
    int dist[N], cnt[N];
    bool st[N];
    
    inline void add(int u, int v, int w)
    {
        ver[++tot] = v, edge[tot] = w, nxt[tot] = head[u], head[u] = tot;
    }
    
    inline bool SPFA()
    {
        memset(dist, 0, sizeof dist);
        memset(cnt, 0, sizeof cnt);
        memset(st, false, sizeof st);
        queue <int> q;
        for (int i = 1; i <= n; i+=1)
        {
            q.push(i); //一开始先将所有的点加入队列
            st[i] = true;
        }
        while (!q.empty())
        {
            int u = q.front(); q.pop();
            st[u] = false;
            for (int i = head[u]; i; i = nxt[i])
            {
                int v = ver[i], w = edge[i];
                if (dist[v] > dist[u] + w)
                {
                    dist[v] = dist[u] + w;
                    cnt[v] = cnt[u] + 1; //记录每个点最短路经的条数
                    if (cnt[v] >= n) return true; //存在负环
                    if (!st[v])
                    {
                        st[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        return false;
    }
    
    int main()
    {
        cin >> f;
        while (f--)
        {
            cin >> n >> m >> w;
            memset(head, 0, sizeof head);
            tot = 0;
            for (int i = 1; i <= m; i+=1)
            {
                int u, v, w;
                cin >> u >> v >> w;
                add(u, v, w), add(v, u, w);
            }
            for (int i = 1; i <= w; i+=1)
            {
                int u, v, w;
                cin >> u >> v >> w;
                add(u, v, -w);
            }
            if (SPFA()) puts("YES");
            else puts("NO");
        }
        return 0;
    }
    
  • 相关阅读:
    零碎
    Python学习 day03 (续day02)
    Python学习 day02
    Python学习 Day1
    线性表——顺序表
    纠删码简介
    小数转化为分数
    C语言多线程操作
    转载:RAMCloud
    转载:全球级分布式数据库Google Spanner
  • 原文地址:https://www.cnblogs.com/xsl19/p/12399001.html
Copyright © 2020-2023  润新知