【模板】负环(SPFA/Bellman-Ford)/洛谷P3385

题目链接

https://www.luogu.com.cn/problem/P3385

题目大意

给定一个 \(n\) 个点有向点权图,求是否存在从 \(1\) 点出发能到达的负环。

题目解析

\(SPFA\) 单点入队次数 \(\geq n\) ,即存在负环。

时间复杂度 \(O(nm)\)

参考代码

#include <bits/stdc++.h>
#define N 3005
#define M 10005
using namespace std;
const int INF = 0x3f3f3f3f;
struct edge{
    int u, v, w;
};
int n, m, T, d[N];
vector <edge> e;
vector <int> G[N];

int spfa(int s)
{
    queue <int> Q;
    int inQ[N], g[N];
    memset(inQ, 0, sizeof inQ);
    memset(g, 0, sizeof g);
    for (int i = 1; i <= n; ++i) d[i] = INF;
    d[s] = 0, inQ[s] = 1, g[s] = 1;
    Q.push(s);
    while (!Q.empty()) {
        int x = Q.front(); Q.pop();
        inQ[x] = 0;
        for (int i = 0; i < G[x].size(); ++i) {
            int b = e[G[x][i]].v, c = e[G[x][i]].w;
            if (d[b] > d[x] + c) {
                d[b] = d[x] + c;
                if (!inQ[b]) {
                    inQ[b] = 1;
                    g[b] ++;
                    Q.push(b);
                    if (g[b] >= n) return 1;
                }
            }
        }
    }
    return 0;
}
void addEdge(int u, int v, int w)
{
    e.push_back((edge){u, v, w});
    G[u].push_back(e.size()-1);
}
int main()
{
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &n, &m);
        e.clear();
        for (int i = 0; i <= n; i++) G[i].clear();
        for (int i = 0; i < m; i++) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            addEdge(a, b, c);
            if (c >= 0) addEdge(b, a, c);
        }
        if (spfa(1)) printf("YES\n");
        else printf("NO\n");
    }
    return 0;  
}
posted @ 2020-11-28 20:43  Chiron-zy  阅读(120)  评论(0编辑  收藏  举报