链接
解析
找有多少个强连通分量中点的个数大于1,将强连通分量染色,染色为第几个强连通分量。然后计算同一个强连通分量的点的个数。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <map>
#include <vector>
#include <stack>
#include <cmath>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn = 10000+100;
typedef long long LL;
int dfn[maxn], low[maxn], ans[maxn];
stack<int>s;
int scc_cnt;
int sccno[maxn];
int dfs_clock;
vector<int>g[maxn];
void init() {
scc_cnt = 0;
dfs_clock = 0;
while (!s.empty())
s.pop();
for (int i=0; i<maxn; i++)
g[i].clear(), dfn[i] = 0, low[i] = 0, sccno[i]=0;
}
void tarjan(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]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (!sccno[v])
low[u] = min(dfn[v], low[u]);
}
if (dfn[u] == low[u]) {
scc_cnt++;
for (;;) {
int x = s.top();
s.pop();
sccno[x] = scc_cnt;
if (x == u)
break;
}
}
}
int main()
{
int n, m;
while (scanf("%d%d", &n, &m)!=EOF) {
init();
memset(ans, 0, sizeof(ans));
for (int i=0; i<m; i++) {
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
}
for (int i=1; i<=n; i++) {
if (!dfn[i])
tarjan(i);
}
for (int i=1; i<=n; i++)
ans[sccno[i]]++;
int res=0;
for (int i=1; i<=scc_cnt; i++)
if (ans[i] > 1)
res++;
printf("%d\n", res);
}
return 0;
}