【洛谷P3388 割點】
阿新 • • 發佈:2017-11-18
輸入格式 != 無向圖 from int oid == ++ 輸出格式
題目描述
給出一個n個點,m條邊的無向圖,求圖的割點。
輸入格式:
第一行輸入n,m
下面m行每行輸入x,y表示x到y有一條邊
輸出格式:
第一行輸出割點個數
第二行按照節點編號從小到大輸出節點,用空格隔開
輸入樣例:
6 7 1 2 1 3 1 4 2 5 3 5 4 5 5 6
輸出樣例:
1 5
說明
n,m均為100000
tarjan 圖不一定聯通!!!
題解
裸的tarjan模板。一個點為割點:1.不為根節點且dfn[now]<=low[e[i].to] 2.為根節點且有超過兩個子樹
1 #include<iostream> 2#include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 using namespace std; 6 struct node 7 { 8 int next,to; 9 } e[200005]; 10 int head[100005],cut[100005],cnt=1,from[100005]; 11 int dfn[100005],low[100005],time; 12 inline void insert(int u,int v) 13 { 14 e[++cnt].next=head[u]; 15 head[u]=cnt;16 e[cnt].to=v; 17 } 18 inline void tarjan(int now,int rt) 19 { 20 int num=0; 21 dfn[now]=low[now]=++time; 22 for(int i=head[now];i;i=e[i].next) 23 { 24 if(i==(from[now]^1)) continue; 25 if(!dfn[e[i].to]) 26 { 27 from[e[i].to]=i; 28 tarjan(e[i].to,rt);29 low[now]=min(low[now],low[e[i].to]); 30 if(dfn[now]<=low[e[i].to] && now!=rt) cut[now]=1; 31 if(now==rt) num++; 32 } 33 else low[now]=min(low[now],dfn[e[i].to]); 34 } 35 if(now==rt && num>=2) cut[now]=1; 36 } 37 int main() 38 { 39 int n,m,u,v,ans=0; 40 scanf("%d%d",&n,&m); 41 for(int i=1;i<=m;i++) 42 { 43 scanf("%d%d",&u,&v); 44 insert(u,v); 45 insert(v,u); 46 } 47 for(int i=1;i<=n;i++) 48 if(!dfn[i]) tarjan(i,i); 49 for(int i=1;i<=n;i++) if(cut[i]) ans++; 50 printf("%d\n",ans); 51 for(int i=1;i<=n;i++) if(cut[i]) printf("%d ",i); 52 return 0; 53 }
【洛谷P3388 割點】