別人寫的對割點的詳細介紹
無向圖求點割集演算法
出處:黑書上給出了關於求點割集的演算法,但是比較模糊,我查閱了網路上的相關資料,理解了求點割集的過程,寫出如下求點割集的**,並寫了一些簡單的證明.
割點集的定義:如果在連通圖g中去掉某一點後圖不連通,那麼這個點即為g的割點,所有割點的集合即為點割集。
求點割集的方法:利用tarjan演算法的思想,用陣列dfn[v]儲存dfs遍歷到點v的時間,陣列low[v]儲存點v能追溯到最早的祖先節點。
如果對於點v來說有如下結論:
1.如果點v是dfs序列的根節點,則如果v有乙個以上的孩子,則v是乙個割點。
2.如果v不是dfs序列根節點,並且點v的任意後繼u能追溯到最早的祖先節點low[u]>=dfn[v],則v是乙個割點。
證明1:
假設dfs遍歷的第乙個節點v不是割點,那麼則有low[v]=dfn[v]=1,繼續對v的孩子節點u遍歷,必然有low[u]>=dfn[v],按照第二條性質,則v是割點,但我們已經假設v不是割點。這是由於v是dfs遍歷的起始節點,在遍歷序列中v沒有祖先節點,v的所有後繼節點能追溯到最早的祖先節點最多也就是v了,不可能比v再早了,因此必須把dfs遍歷的第乙個節點v單獨考慮,那麼怎麼判斷v是不是割點呢?
例如上圖,設v是dfs序列訪問的第乙個節點,對v的孩子節點u和u的所有孩子節點進行dfs遍歷並標記為已經訪問後,如果v的另乙個孩子節點k沒有被標記為已經訪問,那麼u和k之間一定不存在邊,也就是說u和k之間的連通必然需要點v,因此如果v是dfs遍歷的第乙個節點,對v是否為割點的判斷方法是:看v是不是有多個孩子,如果有則v是割點。
證明2:
如果v不是dfs遍歷的第乙個節點,那麼對於v的所有後繼節點來說,如果v不是割點(也就是如果刪掉點v,剩下的圖還是連通圖),那麼v的後繼節點必然能追溯到dfs遍歷序列中v的祖先節點,也就是v的後繼節點中存在到達dfs序列中v的祖先的路徑,因此當dfs回溯到v節點時對於v的所有後繼節點u來說,都有low[u]=dfn[v],這是因為,當遍歷v並將其鎖定後,到達v的祖先節點的路徑已經被封死,v的後繼節點必然不可能訪問到v的祖先節點,因此,必然有low[u]>=dfn[v]。
#include #include #include #include using namespace std;
const int m = 150;
int dfn[m], low[m],vist[m], flag[m];
vectorque[m];
int n, index, root;
int ans;
void init()
void tarjian(int u) else if(v != u)
low[u] = min(low[u], dfn[v]);
}}int main()
}tarjian(1);
ans = 0;
for(int i = 1; i <= n; i++)
if(flag[i])
ans++;
printf("%d\n", ans);
}return 0;
}
poj1144 求割點模板
以後這種模板還是看書比較好,網上的部落格都講得不是很好,推薦lyd寫的 演算法競賽高階指南 寫的,比較現代化 是的我就是在嫌棄紫書白書 然後講解的也通俗易懂。在各類tarjan演算法中,dfn i 表示到達i的序號,low i 表示i所能間接到達的點中dfn最小的值。那麼如果乙個點u是割點,如果他是...
poj 1144 求割點 太奇怪了。。。。
求割點數很簡單 難在一些細節 到現在還不清楚為什麼一開始就設定dfn為1為什麼會錯 錯誤的 view code include include int n,son,ans int map 1000 1000 int dfn 1000 low 1000 int vis 1000 int tdfn in...
poj1144 求割點的個數(注意輸入的格式)
描述 線公司 tlc 正在建立乙個新的 電纜網路。它們連線了幾個從1到n的整數編號的位置。沒有兩個地方有相同的號碼。線路是雙向的,並且總是將兩個地方連線在一起,並且在每個地方線路終止於 交換機。每個地方都有乙個 交換機。它來自每個地方 可以通過其他地方的線路到達,但它不需要是直接連線,它可以通過幾個...