洛谷题单指南-最短路-P3385 【模板】负环

原题链接:https://www.luogu.com.cn/problem/P3385

题意解读:找到从1出发的负环,存在输出YES,不存在输出NO。

解题思路:

1、前置知识:SPFA算法 https://www.cnblogs.com/jcwy/p/18803811

2、核心思想:在SPFA算法中,每一次进行松弛操作,可以同步更新每个点到起点最短路的边数。

设cnt[i]表示i到起点的最短路边数,在松弛操作时对其同步更新:

if(dist[u] + w < dist[v])
{
    dist[v] = dist[u] + w;
    cnt[v] = cnt[u] + 1;
}

如果出现某个cnt[v]值>=n,则说明最短路有n条边,有n+1个点,由于一共只有n个点,必然存在环,且为负环。

3、扩展思考1:如果从起点无法走到负环,如何解决?

对于此情况,图形并不连通,可以假设一个虚拟起点s,s到所有点之间连一条长度为0的虚拟边,

这样,初始将s入队,并将其所有邻接点进行松弛操作后入队!

因此,我们可以初始直接将所有节点入队,并设置所有点的最短路径为0,再继续进行SPFA的处理即可。

4、扩展思考2:如果由于部分数据导致O(nm)复杂度超时,如何解决?

可以统计所有节点被松弛更新的总次数,那么如果超过一定阈值,可以想象可能意味着在负环中绕圈,负值设定是个经验值,比如2n、3n,在极端超时的情况下,往往可以解决问题。

还有一种方法,就是将队列换成堆栈,利用后进先出的特性会便于更快找到负环。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 6005;
int h[N], e[N], w[N], ne[N], idx;
int dist[N], cnt[N];
bool vis[N];
int n, m;

void add(int a, int b, int c)
{
    e[++idx] = b;
    w[idx] = c;
    ne[idx] = h[a];
    h[a] = idx;
}

bool spfa()
{
    memset(dist, 0x3f, sizeof(dist));
    memset(vis, 0, sizeof(vis));
    memset(cnt, 0, sizeof(cnt));
    dist[1] = 0;
    queue<int> q;
    q.push(1);

    while(q.size())
    {
        int u = q.front(); q.pop();
        vis[u] = false;
        for(int i = h[u]; i != -1; i = ne[i])
        {
            int v = e[i];
            if(dist[u] + w[i] < dist[v])
            {
                dist[v] = dist[u] + w[i];
                cnt[v] = cnt[u] + 1;
                if(cnt[v]>= n) return true;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v] = true;
                }
            }
        }
    }

    return false;
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        memset(h, -1, sizeof(h));
        idx = 0;
        cin >> n >> m;
        while(m--)
        {
            int u, v, w;
            cin >> u >> v >> w;
            add(u, v, w);
            if(w >= 0) add(v, u, w);
        }
        if(spfa()) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
}

 

posted @ 2025-04-02 16:46  hackerchef  阅读(79)  评论(0)    收藏  举报