有一个 n 个点,m 条边的有向图,请求出这个图点数大于 1 的强联通分量个数。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<math.h>
#include<set>
using namespace std;
vector<int>p[10010];
stack<int>s;
bool book[10010], vis[10010];
int dfn[10010], low[10010], step = 1, f;//dfn[]记录到达的时间,low[]记录到达的最近的点
int a[10010], sum = 0;
void tarjan(int x)
{
dfn[x] = low[x] = step++;
s.push(x);//入栈
book[x] = vis[x] = true;
for (int i = 0; i < p[x].size(); i++)
{
int c = p[x][i];
if (!dfn[c])
{
tarjan(c);
low[x] = min(low[x], low[c]);//回溯
}
else
{
if (vis[c])//如果还在栈内,更新low[]
{
low[x] = min(low[x], dfn[c]);
}
}
}
if (low[x] == dfn[x])
{
sum++;//强连通分量的数量
do
{
f = s.top();
vis[f] = false;
s.pop();
a[sum]++;
} while (x != f);//x及前面的点都出栈
}
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int x, y;
cin >> x >> y;
p[x].push_back(y);
}
for (int i = 1; i <= n; i++)
{
if (!book[i])
{
tarjan(i);//保证所有点都有访问到
}
}
int ans = 0;
for (int i = 1; i <= sum; i++)
{
if (a[i] > 1)
{
ans++;
}
}
cout << ans;
return 0;
}
样例输入
5 4
2 4
3 5
1 2
4 1
样例输出
1