有向圖找負環 (Negative-Cycle)

CSES - 1197 - Cycle Finding

CSES - 1197 - Cycle Finding

  • 卡車說可以從一個假點開始做 SSSP,也就是將所有點的距離都先設成 0。
  • 我的寫法複雜度看起來不好,感覺假解了,但想不到該怎麼改,可能會 TLE。
  • 想了一個確定複雜度是 O(VE) 的解,將整張圖做 SCC,形成一個 DAG,從每個 in-degree 為 0 的 SCC 選一個點做 DFS。
 1#include<bits/stdc++.h>
 2using namespace std;
 3typedef long long ll;
 4typedef pair<int, ll> pii;
 5#define pb push_back
 6vector<int> ans;
 7vector<vector<pii>> G;
 8vector<bool> visit;
 9vector<bool> use;
10vector<ll> dis;
11int dfs(int v) {
12    use[v] = visit[v] = true, ans.pb(v);
13    for (pii e : G[v]) {
14        int u = e.first;
15        ll w = e.second;
16        if (dis[u] <= dis[v] + w) continue;
17        dis[u] = dis[v] + w;
18        if (visit[u]) return u;
19        int ret = dfs(u);
20        if (ret) return ret;
21    }
22    visit[v] = false, ans.pop_back();
23    return 0;
24}
25int solve(int n) {
26    for (int i = 1, ret; i < n; i++)
27        if (!use[i] && (ret = dfs(i))) return ret;
28    return 0;
29}
30bool SPFA (int n) {
31    queue<int> q;
32    vector<int> cnt(n);
33    vector<bool> inque(n);
34    for (int i = 1; i < n; i++) {
35        if (cnt[i]) continue;
36        inque[i] = 1, q.push(i);
37        while (!q.empty()) {
38            int u = q.front(); q.pop();
39            inque[u] = false;
40            for (pii p : G[u]) {
41                int uu = p.first; ll w = p.second;
42                if (dis[uu] > dis[u] + w) {
43                    dis[uu] = dis[u] + w, cnt[uu]++;
44                    if (cnt[uu] > n) return false;
45                    if (!inque[uu]) inque[uu] = true, q.push(uu);
46                }
47            }
48        }
49    } return true;
50}
51int main() {
52    ios_base::sync_with_stdio(0); cin.tie(0);
53    int n, m; cin >> n >> m; n++;
54    G.resize(n), visit.resize(n), dis.resize(n), use.resize(n);
55    for (int i = 0; i < m; i++) {
56        int a, b; ll c; cin >> a >> b >> c;
57        if (a == b && c < 0) // loop
58            cout << "YES\n" << a << ' ' << b << "\n";
59        G[a].pb(pii(b, c));
60    }
61    if (SPFA(n)) { cout << "NO\n"; return 0;}
62    int v = solve(n), flag = 0;
63    cout << "YES\n";
64    for (int x : ans) {
65        if (x == v) flag = 1;
66        if (flag) cout << x << " ";
67    }
68    cout << v << "\n";
69    return 0;
70}
Built with Hugo
Theme Stack designed by Jimmy