题目背景
割点
题目描述
给出一个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; }