【模板-图论】Tarjan 有向图 强连通分量判定
作者:
acwing_kai
,
2020-09-09 21:47:18
,
所有人可见
,
阅读 699
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010, maxm = 500010;
int n, m, head[maxn], Next[maxm], ver[maxm], tot, num;
int dfn[maxn], low[maxn], cnt, c[maxn]; // cnt = 连通块个数; c[x]表示x所在的强连通分量的编号
bool vis[maxn]; //元素是否在栈中
stack<int> s;
vector<int> scc[maxn];
void add(int x, int y){
ver[++ tot] = y;
Next[tot] = head[x], head[x] = tot;
}
void tarjan(int x){
dfn[x] = low[x] = ++ num;
s.push(x); vis[x] = 1; //
for(int i = head[x]; i; i = Next[i]){
int y = ver[i];
if(dfn[y] == 0){
tarjan(y);
low[x] = min(low[x], low[y]);
}else if(vis[y]) low[x] = min(low[x], low[y]); //
}
if(low[x] == dfn[x]){
cnt ++;
int y;
do{
y = s.top();
s.pop();
vis[y] = 0;
c[y] = cnt;
scc[cnt].push_back(y);
}while(x != y);
}
}
void output(){
for(int i = 1; i <= n; ++ i){
cout << i << " " << c[i] << endl;
}
cout << endl;
for(int i = 1; i <= cnt; ++ i){
cout << "No." << i << ": "<< endl;
for(auto it: scc[i]){
cout << it << " ";
}
cout << endl;
}
}
int main(){
cin >> n >> m;
for(int i = 0, x, y; i < m; ++ i){
cin >> x >> y;
if(x == y) continue;
add(x, y);
}
for(int i = 1; i <= n; ++ i)
if(!dfn[i]) tarjan(i);
output();
}
input:
7 9
1 2
2 3
3 4
4 2
4 5
3 5
1 6
6 7
7 1
output:
1 3
2 2
3 2
4 2
5 1
6 3
7 3
No.1:
5
No.2:
4 3 2
No.3:
7 6 1
这个位置 写错了吧
zc一波