【洛谷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 } 

 

转载于:https://www.cnblogs.com/Dndlns/p/7857600.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值