思想:
做一遍dfs,用dfn[i]表示編號為i的節點在dfs過程中的訪問序號(也可以叫做開始時間)用low[i]表示i節點dfs過程中i的下方節點所能到達的開始時間最早的節點的開始時間。初始時dfn[i]=low[i]
在dfs過程中會形成一搜尋樹。在搜尋樹上越先遍歷到的節點,顯然dfn的值就越小。
dfs過程中,碰到哪個節點,就將哪個節點入棧。棧中節點只有在其所屬的強連通分量已經全部求出時,才會出棧。
如果發現某節點u有邊連到搜尋樹中棧裡的節點v,則更新u的low 值為dfn[v](更新為low[v]也可以)。
如果乙個節點u已經dfs訪問結束,而且此時其low值等於dfn值,則說明u可達的所有節點,都不能到達任何在u之前被dfs訪問的節點
---- 那麼該節點u就是乙個強連通分量在dfs搜尋樹中的根。
此時將棧中所有節點彈出,包括u,就找到了乙個強連通分量
以poj 1236 network of schools 為例說明
192k
0ms#include
#include
#define v
105#define e
100500
struct edge
edge[e];
int head[v], e, n;
int indeg[v], outdeg[v]; //點的入度和出度數
int belong[v], low[v], dfn[v], scc, cnt;//dfn:遍歷到u點的時間;
low:u點可到達的各點中最小的dfn[v]
int s[v], top;
bool vis[v];//v是否在棧中
int addedge(int u, int v)
void tarjan(int u)
else if
(vis[v] && low[u] >
dfn[v])//v在棧中,修改low[u]
low[u] =
dfn[v];
}if (dfn[u]
== low[u])//u為該強連通分量中遍歷所成樹的根
while (u
!= v);}}
int solve()
void count_deg()}}
int main()
printf("%d\n%d\n", inc, (inc > outc ? inc :
outc));}}
return0;}
POJ 1236 tarjan 強連通分量 縮點
poj1236 問,對於乙個dag 又向無環圖 1.至少要選幾個點,才能從這些點出發到達所有點 2.至少加入幾條邊,就能從圖中任何乙個點出發到達所有點 先求dag的強連通分量數,再縮點,可以用tarjan演算法來做。第乙個問題 不難想到答案就是縮點之後入度為0的點的個數 第二個問題 設縮點後入度為0...
LCA問題的Tarjan演算法(POJ1330)
lca問題 least common ancestors,最近公共祖先問題 是指給定一棵有根樹t,給出若干個查詢lca u,v 通常查詢數量較大 每次求樹t中兩個頂點u和v的最近公共祖先,即找乙個節點,同時是u和v的祖先,並且深度盡可能大 盡可能遠離樹根 lca問題有很多解法 線段樹 tarjan演...
POJ 1236 強連通分量
題目鏈結 翻譯一下題目吧,大致含義就是,有n個學校,現在要向n個學校傳遞乙個軟體,如果a學校願意支援b學校,那麼給了a,a就會給b,但是a支援b但是b不一定支援a 有向圖警告 要求什麼呢,最少給多少個學校就可以給到全部的學校,最少加幾個支援關係,可以使得給任意乙個學校就可以傳遞到全部學校去。思路 第...