这个算法网上很容易找到详解,其实认真看一遍百度百科也就懂得七七八八了
再附详解地址,这位博主也是转别人的,但是那个别人的博客打不开了
https://blog.youkuaiyun.com/qq_34374664/article/details/77488976
这个算法的核心思想:将连通分量的各个点用一个点表示。
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <stack>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 551
int DFN[MAXN], Low[MAXN];
int vis[MAXN], sta_ck[MAXN];
int Index, cnt, tot;
int n;
struct Node
{
int to;
int next;
}node[MAXN];
int head[MAXN];
//用head作为头指针指向下一个结点下标,让next指向head指向的下标后,head指向该结点
void add(int x, int y)
{
node[++cnt].next = head[x];
node[cnt].to = y;
head[x] = cnt;
}
void tarjan(int x)
{
DFN[x] = Low[x] = ++tot;
sta_ck[++Index] = x;
vis[x] = 1;
for(int i = head[x]; i != -1; i = node[i].next)
{
if(!DFN[node[i].to])
{
tarjan(node[i].to);
Low[x] = min(Low[x], Low[node[i].to]);
}
else if(vis[node[i].to])
Low[x] = min(Low[x], DFN[node[i].to]);
}
if(Low[x] == DFN[x])
{
do
{
cout << sta_ck[Index] <<" ";
vis[sta_ck[Index]]=0;
Index--;
}while(x != sta_ck[Index + 1]);
cout << endl;
}
}
int main()
{
memset(head, -1, sizeof(head));
memset(DFN, 0, sizeof(DFN));
memset(Low, 0, sizeof(Low));
int n, m;
cin >>n >>m;
int x, y;
for(int i = 1; i <= m; ++i)
{
cin >>x >>y;
add(x, y);
}
for(int i = 1; i <= n; ++i)
if(!DFN[i])
tarjan(i);
return 0;
}