求有向图的强连通分量 Tarjan算法学习笔记
网上翻了很多篇博客都比较难懂,最后终于找到一篇好理解的
推荐给大家http://blog.csdn.net/acmmmm/article/details/16361033
认真看肯定能懂,我当时是只用了十分钟就看明白了,写的真的很易懂。
不过他的代码我是没看懂,这里给一份我自己写的代码。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int MAXN = 10005;
bool is_instack[MAXN];//记录节点是否在栈中
int mystack[MAXN],top;
bool map[MAXN][MAXN];//存图,这里用的矩阵仅供理解,具体做题自己调整
int DFN[MAXN];//记录节点第一次被访问时的时间
int LOW[MAXN];//记录节点与节点的子树节点中最早的步数
int times;
int Belong[MAXN];//记录每个节点属于的强连通分量编号
int N,M,cnt;//N是点数M是边数,cnt是强连通分量编号
void Tarjan(int x){
DFN[x] = LOW[x] = ++times;
is_instack[x] = true;
mystack[++top] = x;
for(int i=0 ; i<N ; i++){//这里注意根据题进行更改
if(map[x][i] == false)continue;
if(!DFN[i]){
Tarjan(i);
if(LOW[i]<LOW[x]){
LOW[x] = LOW[i];
}
}
else if(is_instack[i]){
LOW[x] = min(LOW[x],DFN[i]);
}
}
if(DFN[x] == LOW[x]){
++cnt;
int mid;
do{
mid = mystack[top--];
is_instack[mid] = false;
Belong[mid] = cnt;
}while(mid != x);
}
}
void init(){
memset(map,false,sizeof(map));
memset(DFN,0,sizeof(DFN));
memset(LOW,0,sizeof(LOW));
memset(is_instack,false,sizeof(is_instack));
times = cnt = top = 0;
}
int main(){
while(cin>>N>>M){
init();
for(int i=0 ; i<M ; i++){
int a,b;
cin>>a>>b;
map[a][b] = true;
}
for(int i=1 ; i<=N ; i++){
if(!DFN[i])Tarjan(i);//有可能不是连通图所以遍历一遍
}
}
return 0;
}