模板:割点

日常tarjan

模板

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=1000010;
 6 struct edge{
 7     int to, next;
 8 }a[maxn*2];
 9 int head[maxn], cnt=0;
10 int dfn[maxn], low[maxn], num=0;
11 bool cut[maxn];
12 int n, m, tot=0;
13 void add(int u, int v){
14     cnt++;
15     a[cnt].to=v;
16     a[cnt].next=head[u];
17     head[u]=cnt;
18 }
19 void tarjan(int u, int fa){
20     dfn[u]=low[u]=++num;
21     int child=0;
22     for(int i=head[u]; i; i=a[i].next){
23         int v=a[i].to;
24         if(dfn[v]){
25             tarjan(v, fa);
26             low[u]=min(low[u],low[v]);
27             if(low[v]>=dfn[u] && u!=fa) cut[u]=true;
28             // 非根节点如果 low[v]>=dfn[u]即为割点 
29             if(u==fa) child++;//统计子树 
30         }
31         low[u]=min(low[u],dfn[v]);
32     }
33     if(child>=2 && u==fa) cut[u]=true;
34     //对于根节点来说,如果有两颗以上的子树,就是割点
35     //因为去掉之后两棵子树不能互达 
36 }
37 int main(){
38     memset(dfn,0,sizeof(dfn));
39     memset(head,0,sizeof(head));
40     scanf("%d%d",&n,&m);
41     for(int i=1; i<=m; i++){
42         int a, b;
43         scanf("%d%d",&a,&b);
44         add(a, b);
45         add(b, a);
46     }
47     for(int i=1; i<=n; i++)
48         if(!dfn[i])    tarjan(i, i);
49     for(int i=1; i<=n; i++)
50         if(cut[i])    tot++;
51     printf("%d
",tot);
52     for(int i=1; i<=n; i++)
53         if(cut[i]) printf("%d ",i);
54     return 0;
55 }
原文地址:https://www.cnblogs.com/Aze-qwq/p/9914002.html