Tarjan求强连通分量

看一下code回忆一下就OK了。

 

如下:

中间有自己当时的思考(很有道理的样子)

/*2012-12-06 20:16:08    Accepted    1269    46MS    1484K    1339 B    C++*/
/*
HDU 1269 迷宫城堡 
*/
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
#define maxn 10010

int n;
vector<int> g[maxn];

int Bcnt; /// 强连通分量的个数;
int Top; /// 栈顶;
int Index; /// 时间戳;
int low[maxn], dfn[maxn];
int belong[maxn], stack[maxn];
bool instack[maxn];

void Init_tarjan()
{
    Bcnt= Top= Index= 0;
    for(int i=1; i<=n; ++i) low[i]= dfn[i]= 0;
}

void Tarjan(int u)
{
    stack[Top++]= u;
    instack[u]= true;
    low[u]= dfn[u]= ++Index;
    for(int i=0; i<g[u].size(); ++i)
    {
        int v= g[u][i];
        if( !dfn[v] ){
            Tarjan(v);
            low[u]= min( low[v], low[u] );
        }
        else if( instack[v] )
            low[u]= min( low[u], dfn[v] );//注意是dfn[v] 并不是low[v] 
            //oh 都怪当初没有写原因
            //现在都不知道为什么了。 
            //但实际上 貌似都是可以的
            //首先是 XMJ这样告诉我了
            /*其次 
            tarjan判断强连通的原理就是
            1.每个点要么自己就是强连通分量的根(自己一个点为一个强连通分量)
            2.要么就是它在以其他点为根的强连通分量里面
            (这里说的根 是在DFS的时候DFN最小的点 ) 
            所以 一旦一个点能够通向一个仍旧在stack中的点
            就说明 它在其他点为根的强连通分量 里面。
            此时 倘若用low[u]= min( low【u】, low【v】 );
            也是非常有道理的
            因为v倘若就是这个根  low【v】==dfn【v】 和上面无区别
            否则 v 和 u 都在另一个点为根的强连通分量里面
            那个根是谁呢?那就是low【v】   
       强连通又是求的极大的强连通子图
       所以,low【u】更新为low【v】再有道理不过了
*/ } if( low[u]==dfn[u] ) { ++Bcnt; int v; do { v= stack[--Top]; instack[v]= false; belong[v]= Bcnt; }while( u!=v ); } } int main() { int m; while( cin>>n>>m, n+m ){ for(int i=1; i<=n; ++i) g[i].clear(); while(m--){ int x, y; scanf("%d%d", &x, &y); g[x].push_back(y); } Init_tarjan(); for(int i=1; i<=n; ++i){ if( !dfn[i] ) Tarjan(i); } puts( Bcnt==1 ? "Yes" : "No" ); } }

 

posted @ 2016-03-21 19:56  A_Cherry  Views(175)  Comments(0)    收藏  举报