割點和割邊

2022-10-11 10:15:12 字數 1812 閱讀 4396

無向圖中,所有能互通的點組成了乙個「連通分量」。在乙個連通分量中有一些關鍵的點,如果刪除它們,會把這個連通分量分成兩個或更多,這種點稱為割點(cut vertex)。

類似的有割邊(cut edge,又稱為橋,bridge)問題。在乙個連通分量中,如果刪除一條邊,把這個連通兩個(注意邊最多只能分成兩個),則這個邊稱為割邊。

在乙個連通分量g中,對任意乙個點s左dfs。能訪問到所有點,產生一顆「深度優先生成樹」。那麼對g求割點,和t有什麼關係呢?

定理1t的根節點時割點,當且僅當s有兩個或更多個子結點。

這個很好理解,如果s是割點,那麼它會把圖分成幾個不相連的部分,這幾個部分對應著t中的不同子樹。

在這個圖中可以很方便的驗證這個定理。

定理2t的非根結點u是割點,當且僅當u存在乙個子結點v,v及其後代都沒有回退邊連回u的祖先(返祖邊,右圖中的虛線)。

這就是說,如果非根結點u是割點,那麼它最起碼會把圖分為上下兩個部分,上面是祖先,下面是後代,並且這兩部分不能相連。

例如上圖的c不是割點而e是割點(它的子結點g及其後代沒有產生返祖邊)。

注意根節點與非根結點的判斷方法不同。

上面那個圖,若按非根結點判斷則a是割點,但實際上它不是割點。

關鍵就在於如何判斷乙個結點是否能訪問到某個結點的祖先。

定義dfn[i]表示i點的時間戳,就是i點是第幾個被訪問到的。

定義low[i]表示i點及其後代能連線到的最早祖先。

現在設u的乙個子結點是v。

如果有low[v]>=dfn[u],就說明通過v回不到u的祖先了。

例題

p3388 【模板】割點(割頂)

參考**

#includeusing namespace std;

const int n=2e4+10;

const int m=1e5+10;

structe[2*m];

int n,m;

int head[n],cnt;

int dfn[n],low[n];

bool is[n];

void add(int a,int b)

int cdfn=0;

int tot;

void dfs(int x,int fr)

else low[x]=min(low[x],dfn[to]);//如果這個結點訪問過,那麼它一定是當前結點的祖先,直接更新low

} if(x==fr&&child>=2)is[x]=1;//判斷根節點是否是割點

}int main()

for(int i=1;i<=n;++i)

for(int i=1;i<=n;++i)if(is[i])++tot;

printf("%d\n",tot);

for(int i=1;i<=n;++i)

return 0;

}

只要將low[v]>=dfn[u]改成low[v]>dfn[u]即可判斷割邊,因為v及其子結點若能到達u,顯然刪除u->v這條邊不能斷開他們。

找割點和割邊

include include using namespace std int n,m,e 9 9 root int num 9 low 9 flag 9 index void dfs int cur,int father else if i father 否則如果頂點i曾經被訪問過,並且這個頂點不...

找割點和割邊

else if i father 否則如果頂點i曾經被訪問過,並且這個頂點不是當前頂點cur的父親 則說明此時的i為cur的祖先,因此需要更新當前節點cur能訪問到最早頂點的時間戳 return int main root 1 dfs 1,root 從1號頂點開始深度優先搜尋 for i 1 i n...

割點 割邊 tarjan

洛谷割點模板題 傳送門 割邊 在連通圖中,刪除了連通圖的某條邊後,圖不再連通。這樣的邊被稱為割邊,也叫做橋。割點 在連通圖中,刪除了連通圖的某個點以及與這個點相連的邊後,圖不再連通。這樣的點被稱為割點。dfs搜尋樹 用dfs對圖進行遍歷時,按照遍歷次序的不同,我們可以得到一棵dfs搜尋樹。樹邊 在搜...