无向图求割点(找桥)tarjan
本博客參考了李煜東的《算法競賽進階指南》,大家要是覺得這篇文章寫的不錯請大家支持正版。豆瓣圖書
我在之前的博客中講解了搜索序時間戳,這次我們講講追溯值的概念。
追溯值:
????設(shè)subtree(x)表示搜索樹中,以X為根的子樹。low[x]定義為一下節(jié)點的時間戳最小值:
????1.subtree(x)中的節(jié)點。
?????2.通過1條不在搜素樹上的邊,能夠到達subtree(x)的節(jié)點。
??????
以上圖為例。為了敘述簡便,我們用時間戳代替節(jié)點編號。subtree(2)={2,3,4,5}。零位,節(jié)點1通過搜索樹邊的(1,5)能夠到達subtree(2)。所以low[2]=1。根據(jù)定義拉算的話,首先應(yīng)該讓low[x]=dfn[x],然后考慮從x出發(fā)的每條邊(x,y);
若在搜素樹上x是y 的父節(jié)點,則令low[x]=min(low[x],low[y]).
若無向邊(x,y)不是搜索樹邊,則令low[x]=min(low[x],dfn[y]).
該圖中寫出了追溯值的圖。
?割點判定法則:
若X不是Y的搜素樹的根節(jié)點(深度遍歷的起點),則x是割點當(dāng)且僅當(dāng)搜索樹上存在X的一個子節(jié)點Y,滿足:
? ?dfn[x]<=low[y]
特別地,若x是搜索樹的根節(jié)點,則x是割點當(dāng)且僅當(dāng)搜索樹上存在至少兩個子節(jié)點y1,y2滿足以上條件。
模板:
#include<iostream> #include<stdio.h> #include<vector> using namespace std; const int maxn=100010; int head[maxn],ver[maxn*2],Next[maxn*2]; int dfn[maxn],low[maxn],sta[maxn]; int n,m,tot,num,root; bool cut[maxn]; void add(int x,int y) {ver[++tot]=y;Next[tot]=head[x];head[x]=tot; } void tarjan(int x) {dfn[x]=low[x]=++num;int flag=0;for(int i=head[x];i;i=Next[i]){int y=ver[i];if(!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);if(low[y]>=dfn[x]){flag++;if(x!=root||flag>1) cut[x]=1;}}else low[x]=min(low[x],dfn[y]);} } int main() {cin>>n>>m;tot=1;for(int i=1;i<=m;i++){int x,y;scanf("%d %d",&x,&y);if(x==y) continue;add(x,y),add(y,x);}for(int i=1;i<=n;i++){if(!dfn[i]) root=i,tarjan(i);}for(int i=1;i<=n;i++)if(cut[i]) printf("%d ",i); }?
總結(jié)
以上是生活随笔為你收集整理的无向图求割点(找桥)tarjan的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 首款 PCIe 5.0 SSD 实测:读
- 下一篇: 图论--最短路--SPFA