洛谷P3388 割点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P3388 割点相关的知识,希望对你有一定的参考价值。

题目描述

  给出一个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 割点的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P3388 割点

洛谷 P3388 模板割点

洛谷P3388 模板割点(割顶)

洛谷P3388 模板割点

P3388 模板割点(割顶)

[模板]割点(tarjan)