您的位置:首页 > 其它

洛谷—— P3388 【模板】割点(割顶)

2017-09-01 17:33 302 查看

https://www.luogu.org/problem/show?pid=3388

题目背景

割点

题目描述

给出一个n个点,m条边的无向图,求图的割点。

输入输出格式

输入格式:

 

第一行输入n,m

下面m行每行输入x,y表示x到y有一条边

 

输出格式:

 

第一行输出割点个数

第二行按照节点编号从小到大输出节点,用空格隔开

 

输入输出样例

输入样例#1:
6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6
输出样例#1:
1
5

说明

n,m均为100000

tarjan 图不一定联通!!!

 

#include <cstdio>

const int N(100000+5);
int ans,head
,sumedge=1;
struct Edge
{
int v,next;
Edge(int v=0,int next=0):v(v),next(next){}
}edge[N<<1];
inline void ins(int u,int v)
{
edge[++sumedge]=Edge(v,head[u]);
head[u]=sumedge;
edge[++sumedge]=Edge(u,head[v]);
head[v]=sumedge;
}

#define min(a,b) (a<b?a:b)
int tim,dfn
,low
,cutpoint
;
void Tarjan(int u,int pre)
{
int sumtredge=0,if_point=0;
dfn[u]=low[u]=++tim;
for(int v,i=head[u];i;i=edge[i].next)
{
v=edge[i].v;
if((pre^1)==i) continue;
if(!dfn[v])
{
sumtredge++;
Tarjan(v,i);
if(low[v]>=dfn[u]) if_point=1;
low[u]=min(low[u],low[v]);
}
else low[u]=min(low[u],dfn[v]);
}
if(!pre)
{
if(sumtredge>1) ans++,cutpoint[u]=1;
}
else if(if_point) ans++,cutpoint[u]=1;
}

int main()
{
int n,m; scanf("%d%d",&n,&m);
for(int u,v;m--;ins(u,v))
scanf("%d%d",&u,&v);
for(int i=1;i<=n;i++)
if(!dfn[i]) Tarjan(i,0);
printf("%d\n",ans);
for(int i=1;i<=n;i++)
if(cutpoint[i]) printf("%d ",i);
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: