本蒟蒻一下tarjan演算法,然後就不知死活的覺得自己應該都會了,然後就在割點上卡了幾天捂臉,來發一篇題解
其實,tarjan演算法的精髓是dfn和low
dfn[i]就是時間戳,即在什麼時刻搜尋到了點i
low[i]則是i點能回溯到的dfn最小的祖先
low[a]=min(low[a],dfn[p]);
ps:
給的圖不一定是連通圖(卡的我啊啊啊)
鏈式前向星開邊要2倍(這個應該都知道吧)
#include
#include
#include
#define for(i,n,m) for(int i=n;i<=m;++i)
#define min(a,b) (a#define re register
#define gc getchar()
using
namespace std;
const
int n=
100010
;inline
intread()
while
(ch>=
'0'&&ch<=
'9')
return x*f;
}//前向星
struct node e[n<<1]
;int h[n<<1]
,n,m,cnt;
#define add(u,v) e[++cnt].next=h[u],e[cnt].to=v,h[u]=cnt;
#define qxx(u) for(int i=h[u],v;v=e[i].to,i;i=e[i].next)
//上面都沒什麼用
//tarjan
int dfn[n]
,low[n]
,vis[n]
,s[n]
,tot,top;
/*dfn :時間戳
low :i及i的子樹中所有結點能到達的結點中dfn最小的結點的時間戳
*/void
tarjan
(int u,
int fa)
else
if(v!=fa) low[u]
=min
(low[u]
,dfn[v]);
//如果乙個點被搜尋過了並且是x的兒子或者是它的父親,就可以直接回溯 }if
(u==fa&&son>=
2) vis[u]=1
;//如果乙個點是根並且有多於兩個子樹,就是割點
}void
work()
for(i,
1,n)if(
!dfn[i]
)tarjin
(i,i)
;int tot=
0,ans[n]
;for
(i,1
,n)if
(vis[i]
) ans[
++tot]
=i; cout
1,tot) cout<<<
" ";
}int
main()
P3388 模板 割點(割頂) 題解
同步 原題鏈結 簡要題意 給定乙個圖,求所有割點。割點 割頂 的定義 去掉該點整個圖不連通。前置知識 強連通分量的 tarjan texttt tarjan 求法。不懂的可以先去了解下 本題作為 tarjan texttt tarjan 求割點的模板題。首先,我們同樣和求強連通分量一樣,搞出乙個 d...
模板 割點(割頂)
給出乙個n個點,m條邊的無向圖,求圖的割點。輸入格式 第一行輸入n,m 下面m行每行輸入x,y表示x到y有一條邊 輸出格式 第一行輸出割點個數 第二行按照節點編號從小到大輸出節點,用空格隔開 n,m均為100000 tarjan 圖不一定聯通!求割點。這可以用到之前學的tarjan。對於一棵生成樹,...
模板 割點(割頂)
題目背景 割點題目描述 給出乙個n個點,m條邊的無向圖,求圖的割點。輸入輸出格式 輸入格式 第一行輸入n,m 下面m行每行輸入x,y表示x到y有一條邊 輸出格式 第一行輸出割點個數 第二行按照節點編號從小到大輸出節點,用空格隔開 輸入輸出樣例 輸入樣例 1 6 7 1 2 1 3 1 4 2 5 3...