P3388 【模板】割点(割顶)

P3388 【模板】割点(割顶)

题目背景

割点

题目描述

给出一个 n 个点,m 条边的无向图,求图的割点。

输入格式

第一行输入两个正整数 n,m

下面 m 行每行输入两个正整数 x,y 表示 xy 有一条边。

输出格式

第一行输出割点个数。

第二行按照节点编号从小到大输出节点,用空格隔开。

输入输出样例 #1

输入 #1

6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6

输出 #1

1 
5

说明/提示

对于全部数据,1n2×1041m1×105

点的编号均大于 0 小于等于 n

tarjan图不一定联通。
卡了好久总算过了,首先没有看清输出要求卡了很久,其次就是计算总数时,有的点会被重复遍历,所以计算总数要单开一个循环,最重要的一点就是注意是lowx还是dfsnx,是lowy还是dfsny

#include<iostream>
#include<vector>
#define int long long 
using namespace std;
const int N=1e5+5;
int n,m,x,y;
int low[N],dfsn[N],vis[N],cut[N];
vector<int>v[N];
int t=0;
int root;
int cnt=0;
vector<int>ans;
void dfs(int x){
    low[x]=dfsn[x]=++t;
    int child=0;
    for(int y:v[x]){
        if(!dfsn[y]){
            dfs(y);
            child++;
            low[x]=min(low[x],low[y]);
            if(x==root&&child>=2||x!=root&&low[y]>=dfsn[x])cut[x]=true;
        }
        else low[x]=min(low[x],dfsn[y]);
    }
}
signed main(){
    cin>>n>>m;
    while(m--){
        cin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    for(int i=1;i<=n;i++)if(!dfsn[i])root=i,dfs(i);
    for(int i=1;i<=n;i++) if(cut[i])cnt++;
    cout<<cnt<<endl;
    for(int i=1;i<=n;i++){
        if(cut[i])cout<<i<<" ";
    }
    return 0;
}
posted @ 2025-03-15 16:06  郭轩均  阅读(31)  评论(0)    收藏  举报
相关博文:
阅读排行:
· 提升Avalonia UI质感,跨平台图标库选型实践
· 突发,CSDN 崩了!程序员们开始慌了?
· C# 中委托和事件的深度剖析与应用场景
· 一个基于 .NET 8 + Ant Design Blazor 开发的简洁现代后台管理框架
· AppBox拖拽设计增删改查用户界面
点击右上角即可分享
微信分享提示