求有向图的强连通分量 Tarjan算法学习笔记

来源:互联网 发布:买家怎样删除淘宝评价 编辑:程序博客网 时间:2024/05/18 18:42

网上翻了很多篇博客都比较难懂,最后终于找到一篇好理解的
推荐给大家http://blog.csdn.net/acmmmm/article/details/16361033
认真看肯定能懂,我当时是只用了十分钟就看明白了,写的真的很易懂。
不过他的代码我是没看懂,这里给一份我自己写的代码。

#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>using namespace std;#define MAXN 10005bool is_instack[MAXN];//记录节点是否在栈中 int stack[MAXN],top;bool map[MAXN][MAXN];//存图,这里用的矩阵仅供理解,具体做题自己调整。int DFN[MAXN];//记录节点第一次被访问时的时间int LOW[MAXN];//记录节点与节点的子树节点中最早的步数 int time; int Belong[MAXN];//记录每个节点属于的强连通分量编号 int N,M,cnt;//N是点数M是边数,cnt是强连通分量编号。int Tarjan(int x){    DFN[x] = LOW[x] = ++time;    is_instack[x] = true;    stack[++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] && DFN[i]<DFN[x]){ //这里注意不能直接else,因为DFN[i]!=0还有可能是横叉边。            LOW[x] = DFN[i];        }    }    if(DFN[x] == LOW[x]){        cnt++;        int mid;        cout<<cnt<<" Find!!!"<<endl;        do{            mid = stack[top--];            is_instack[mid] = false;            cout<<"--"<<mid<<endl;            Belong[mid] = cnt;        }while(mid != x);    }}int main(){    while(cin>>N>>M){        memset(map,false,sizeof(map));        memset(DFN,0,sizeof(DFN));        memset(LOW,0,sizeof(LOW));        time = 0;        cnt = 0;        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;}
阅读全文
0 0