【模板】1:tarjan求割点

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int n,m,idx,cnt,total;
 5 int first[200010],next[200010],to[200010],dfn[100010],low[100010];
 6 bool cut[100010];
 7 void add (int x,int y)
 8 {
 9     to[++cnt]=y;
10     next[cnt]=first[x];
11     first[x]=cnt;//加点,记得反向存图 
12 }
13 void tarjan (int u,int fa)
14 {
15     dfn[u]=low[u]=++idx;//修改时间戳和low值 
16     int child=0;
17     for (int i=first[u];i!=-1;i=next[i])
18     {
19         int nx=to[i];
20         if (dfn[nx]==0)
21         {
22             tarjan (nx,fa);
23             low[u]=min (low[u],low[nx]);
24             if (low[nx]>=dfn[u]&&u!=fa)//是根节点单独讨论 
25                 cut[u]=1;
26             if(u==fa)
27                 child++;
28         }
29         else
30         low[u]=min (low[u],dfn[nx]);
31     }
32     if (child>=2&&u==fa)
33         cut[u]=1;
34 }
35 int main()
36 {
37     scanf ("%d%d",&n,&m);
38     for(int i=1;i<=m;i++)
39     {
40         next[i]=-1;
41     }
42     for(int i=1;i<=n;i++)
43     {
44         first[i]=-1;
45     }
46     for (int i=1;i<=m;i++)
47     {
48         int a,b;
49         scanf ("%d%d",&a,&b);
50         add (a,b);
51         add (b,a);
52     }
53     for (int i=1;i<=n;i++)
54         if (dfn[i]==0)
55             tarjan (i,i);
56     for (int i=1;i<=n;i++)
57         if (cut[i]==1)
58             total++;
59     printf ("%d\n",total);
60     for (int i=1;i<=n;i++)
61         if (cut[i]==1)
62             printf ("%d ",i);
63     return 0;
64 }

                                                                                                                  2019-09-08 By十四日的夏

posted @ 2019-09-08 20:20  十四日的夏  阅读(123)  评论(0编辑  收藏  举报