#include<bits/stdc++.h>
using namespace std;
#define pi acos(-1)
#define mod 1000000007
#define ll long long
#define ull unsigned long long
#define mem(a) memset(a,0,sizeof(a))
#define cio ios::sync_with_stdio(false)
std::vector<int>e[20010];
int dfn[20010]; // 时间戳
int low[20010]; // 追溯值
int s[20010]; // 标记割点
int step; // 步数
int cnt; // 割点数
int root; // 根节点
void tarjan(int x, int y)
{
int child = 0; // 记录当前根节点的子节点个数
dfn[x] = low[x] = ++step;
for(int i = 0; i < e[x].size(); i++){
int p = e[x][i];
if(!dfn[p]){
child++; // 子节点+1
tarjan(p,x);
low[x] = min(low[x],low[p]);
if(x==root&&child>=2){ // 该点为根节点并且子节点个数>1为割点
s[x] = 1;
}else if(x!=root&&low[p]>=dfn[x]){ // 该点不为根节点并且追溯值大于等于根节点的时间戳为割点
s[x] = 1;
}
}else if(p!=y){
low[x] = min(low[x],dfn[p]);
}
}
}
int main()
{
step = 0;
cnt = 0;
int n, m;
cin >> n >> m;
int x, y;
while(m--){
cin >> x >> y;
e[x].push_back(y);
e[y].push_back(x);
}
for(int i = 1; i <= n; i++){
if(!dfn[i]){
root = i;
tarjan(i,i);
}
}
for(int i = 1; i <= n; i++){
if(s[i]==1) cnt++; // 统计割点
}
cout << cnt << endl;
for(int i = 1; i <= n; i++){
if(s[i]==1) cout << i << " ";
}
return 0;
}
Tarjan算法-求割点
最新推荐文章于 2022-12-31 10:26:59 发布