割点 (模板) 洛谷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<iostream>
#include<cstdio>
using namespace std;
const int MAXN = 100010;
struct Edge {
int nxt,to;
} edge[MAXN*2];
int n,m,dfn[MAXN],low[MAXN],tot,cnt;
int head[MAXN],num;
bool cut[MAXN];
inline void add(int bg,int ed) {
edge[++cnt].to=ed;
edge[cnt].nxt=head[bg];
head[bg]=cnt;
}
inline void tarjan(int u,int fa) {
dfn[u]=low[u]=++num;
int child=0;
for(int i=head[u]; i; i=edge[i].nxt) {
int v=edge[i].to;
if(!dfn[v]) {
tarjan(v,fa);
low[u]=min(low[v],low[u]);
if(low[v]>=dfn[u] && u!=fa)
cut[u]=1;
if(u==fa)
child++;
}
low[u]=min(low[u],dfn[v]);
if(child>=2 && u==fa)
cut[u]=1;
}
}
inline void debug() {
for(int i=1; i<=n; i++)
printf("%d %d %d\n",i,dfn[i],low[i]);
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++) {
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(int i=1; i<=n; i++)
if(!dfn[i]) tarjan(i,i);
//debug();
for(int i=1; i<=n; i++)
if(cut[i]) tot++;
printf("%d\n",tot);
for(int i=1;i<=n;i++){
if(cut[i])
printf("%d ",i);
}
return 0;
}