算法实现
在dfs基础上,出现重复的 在栈中的 点,我们就将它进行一次缩点
就是low[] 数组维护的当前这个强联通分量(形成环的部分)的 最小dfs序的 cnt
缩点之后将这些 所有被缩的点 弹出栈
时空复杂度
O(N + M)
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
#include <set>
#include <vector>
#include <stack>
#define Clear( x , y ) memset( x , y , sizeof(x) );
#define Qcin() std::ios::sync_with_stdio(false);
using namespace std;
typedef long long LL;
const int Maxn = 1e6 + 7;
const int Inf = 1e9 + 7;
int N , M;
struct Edge{
int nxt;
int to;
}edge[Maxn];
int head[Maxn];
int cnt , dfs[Maxn];
int color , col[Maxn] , low[Maxn];
stack <int> st;
bool vis[Maxn];
void tarjan(int x){
dfs[x] = ++cnt;
low[x] = cnt;
vis[x] = 1;
st.push(x);
int v;
for(int i = head[x] ; ~i ; i = edge[i].nxt){
v = edge[i].to;
if(!dfs[v]){
tarjan(v);
low[x] = min(low[x] , dfs[v]);
}
if(vis[v]) low[x] = min(low[x] , dfs[v]);
}
if(low[x] == dfs[x]){
col[x] = ++color;
vis[x] = 0;
int p;
while(!st.empty() && st.top() != x){
vis[st.top()] = 0;
st.pop();
}
if(!st.empty()) st.pop();
}
}
void init(){
cnt = color = 0;
for(int i = 1 ; i <= N ; ++i) head[i] = -1;
}
int main()
{
init();
for(int i = 1 ; i <= N ; ++i){
if(!dfs[i]){
tarjan(i);
}
}
}