您的位置:首页 > 其它

P3388 【模板】割点(割顶)

2017-11-25 17:31 253 查看

P3388 【模板】割点(割顶)

题目背景

割点

题目描述

给出一个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 图不一定联通!!!

分析

tarjan求割点

code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>

using namespace std;

const int N = 100100;
struct Edge{
int to,nxt;
}e[N<<1];
int head
,dfn
,low
;
bool iscut
;
int tn,tot;

inline char nc() {
static char buf[100000],*p1 = buf,*p2 = buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++;
}
inline int read() {
int x = 0,f = 1;char ch = nc();
for (; ch<'0'||ch>'9'; ch = nc())
if (ch=='-') f = -1;
for (; ch>='0'&&ch<='9'; ch = nc())
x = x*10+ch-'0';
return x * f;
}

void add_edge(int u,int v) {
e[++tot].to = v,e[tot].nxt = head[u],head[u] = tot;
}

void tarjan(int u,int fa) {
low[u] = dfn[u] = ++tn;
int cnt_son = 0;
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (!dfn[v]) {
cnt_son++;
tarjan(v,u);
low[u] = min(low[u],low[v]);
if (low[v] >= dfn[u])
iscut[u] = true;
}
else if (dfn[v] < dfn[u] && v != fa)
low[u] = min(low[u],dfn[v]);
}
if (fa<0 && cnt_son==1) iscut[u] = false;
}
int main() {
int n = read(),m = read();
for (int u,v,i=1; i<=m; ++i) {
u = read(),v = read();
add_edge(u,v),add_edge(v,u);
}
for (int i=1; i<=n; ++i)
if (!dfn[i]) tarjan(i,-1);

int ans = 0;
for (int i=1; i<=n; ++i)
if (iscut[i]) ans++;
printf("%d\n",ans);
for (int i=1; i<=n; ++i)
if (iscut[i]) printf("%d ",i);
return 0;
}

 

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