UVALive ~ 4287 ~ Proving Equivalences (強連通分量+縮點)
阿新 • • 發佈:2018-12-16
#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
*/