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" ); } }

浙公网安备 33010602011771号