1. 程式人生 > >UVALive ~ 4287 ~ Proving Equivalences (強連通分量+縮點)

UVALive ~ 4287 ~ Proving Equivalences (強連通分量+縮點)

在這裡插入圖片描述

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;

int DFN[MAXN], LOW[MAXN], sccno[MAXN], dfs_clock, scc_cnt;
stack<int> S;
vector<int> G[MAXN];
void init(int n){ for (int i = 0; i <= n; i++) G[i].clear(); }
void dfs(int u)
{
    DFN[u] = LOW[u] = ++dfs_clock;
S.push(u); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (!DFN[v]) { dfs(v); LOW[u] = min(LOW[u], LOW[v]); } else if (!sccno[v]) LOW[u] = min(LOW[u], DFN[v]); } if (LOW[u] == DFN[u]) {
scc_cnt++; while (1) { int x = S.top(); S.pop(); sccno[x] = scc_cnt; if (x == u) break; } } } void find_scc(int n) { dfs_clock= scc_cnt = 0; memset(DFN, 0, sizeof(DFN)), memset(sccno, 0, sizeof
(sccno)); for (int i = 0; i < n; i++) if (!DFN[i]) dfs(i); } int n, m, in0[MAXN], out0[MAXN]; int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); init(n); for (int i = 0; i < m; i++) { int u, v; scanf("%d%d", &u, &v); u--, v--; G[u].push_back(v); } find_scc(n); for (int i = 1; i <= scc_cnt; i++) in0[i] = out0[i] = 0; for (int u = 0; u < n; u++) { for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (sccno[u] != sccno[v]) in0[sccno[v]]++, out0[sccno[u]]++; } } int cnt1 = 0, cnt2 = 0; for (int i = 1; i <= scc_cnt; i++) { if (!in0[i]) cnt1++; if (!out0[i]) cnt2++; } int ans = max(cnt1, cnt2); if (scc_cnt == 1) ans = 0; printf("%d\n", ans); } return 0; } /* 2 4 0 3 2 1 2 1 3 */