版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
求一个有向图强连通分量个数以及每个点所属连通分量
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 1e5+10;
vector<int> E[maxn]; // 正向边
vector<int> rE[maxn]; // 反向边
vector<int> a; // 后序遍历图记录下顶点遍历顺序
int vis[maxn];
int cmp[maxn]; // 记录每个顶点所属连通分量编号
void dfs(int u)
{
vis[u] = 1;
for(int i = 0; i < E[u].size(); i++)
{
int v = E[u][i];
if(vis[v]==0) dfs(v);
}
a.push_back(u);
}
void rdfs(int u, int k)
{
vis[u] = 1;
cmp[u] = k;
for(int i = 0; i < rE[u].size(); i++)
{
int v = rE[u][i];
if(vis[v]==0) rdfs(v, k);
}
}
// 返回连通分量个数
int scc(int n)
{
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
if(vis[i]==0) dfs(i);
memset(vis, 0, sizeof(vis));
int k = 0;
for(int i = a.size()-1; i >= 0; i--)
if(vis[a[i]]==0) rdfs(a[i], k++);
return k;
}
int main()
{
int n, m; cin >> n >> m;
while(m--)
{
int u, v; cin >> u >> v;
E[u].push_back(v);
rE[v].push_back(u);
}
int res = scc(n);
cout << res << endl;
return 0;
}
/*
输入
6 10
1 2
2 3
3 1
2 4
4 5
4 6
5 6
5 7
6 5
6 7
*/