1. 程式人生 > >Tarjan割點

Tarjan割點

pre 搜索 感覺 bsp 重要 ioi ros microsoft spa

$Tarjan$求割點

  感覺圖論是個好神奇的東西啊,有各種奇奇怪怪的算法,而且非常巧妙。

  周末之前說好回來之後進行一下學術交流,於是wzx就教給我Tarjan,在這裏我一定要說: $wzx AK IOI$

  Tarjan發明了很多算法,而且還都叫一個名字,所以說只好用用途來區分它們。

  閑聊時間結束。


  首先,什麽是割點呢?在一個無向圖中,如果有一個頂點,刪除這個頂點以及所有相關聯的邊以後,圖的連通分量增多,就稱這個點為割點。

  首先找一個點作為根進行搜索,把圖按照$dfs$的方法組織成一棵搜索樹,樹上的邊一定都是圖上的邊,稱為樹邊,而圖上其余的邊則為非樹邊(回邊)。

  如果一個點不能通過非樹邊而回到比他樹上的父親的$dfs$序更小的點,那麽如果把它樹上的父親刪掉,它就不能通過其他方法與圖的其他部分聯通,它的父親就是一個割點。多麽神奇啊!對於根節點,我們可以發現,如果它有不止一個的子樹,那它就是割點了。看代碼:

  技術分享圖片
 1 void dfs(int x,int roo,int Dad)
 2 {
 3     id[x]=low[x]=++cnt;
 4     int j,cnts=0;
 5     for (R i=firs[x];i;i=g[i].nex)
 6     {
 7         j=g[i].too;
 8         if(!id[j])
 9         {
10             dfs(j,roo,x);
11             low[x]=min(low[x],low[j]);
12             if(x==roo) cnts++;
13 if(low[j]>=id[x]&&x!=roo) f[x]=1; 14 } 15 else 16 { 17 if(j!=Dad) low[x]=min(low[x],low[j]); 18 } 19 } 20 if(x==roo&&cnts>=2) f[x]=1; 21 }
Tarjan求割點

  這裏有一句話還是比較重要的:

 1 if(j!=Dad) low[x]=min(low[x],low[j]);

  是防止重復走樹邊,

其實也可以改成 $low[x]=min(low[x],id[j])$,這樣更新出來的$low$可能不是真正的$low$,但是因為兒子到父親的路徑上不會再有別的點,所以這樣也能保證正確性。

Tarjan割點