题目背景
割点
题目描述
给出一个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
- 题解:注意不是连通图。。。
- 代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
using namespace std;
const int maxn=100005;
int n,m,cnt=0;
int indexx;
int root;
int ans[maxn];
int flag[maxn];
vector<int> e[maxn<<1|1];
int low[maxn],num[maxn];
void dfs(int cur,int father){
int child=0;
indexx++;
low[cur]=indexx;
num[cur]=indexx;
for(int i=0;i<e[cur].size();i++){
int u=e[cur][i];
if(u){
if(!num[u]){
child++;
dfs(u,cur);
low[cur]=min(low[cur],low[u]);
if(cur!=root&&low[u]>=num[cur]){
flag[cur]=1;
}
if(cur==root&&child>=2){
flag[u]=1;
}
}else if(u!=father){
low[cur]=min(low[cur],num[u]);
}
}
}
}
int main()
{
int x,y;
scanf("%d %d",&n,&m);
for(int i=0;i<m;i++){
scanf("%d %d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
memset(flag,0,sizeof flag);
memset(num,0,sizeof num);
memset(low,0,sizeof low);
root=1,cnt=0;
for(int i=1;i<=n;i++){
root=i;
if(!num[i])
dfs(i,root);
}
int j=0;
for(int i=1;i<=n;i++){
if(flag[i]){
cnt++;
ans[j++]=i;
}
}
printf("%d
",cnt);
if(ans[0]) printf("%d",ans[0]);//这里有三个测试点,当割点个数为0的时候后面就不要输出了
for(int i=1;i<j;i++){
printf(" %d",ans[i]);
}
//printf("
");
return 0;
}