洛谷 P3388:【模板】割点(割顶)← Tarjan 算法

【题目来源】
https://www.luogu.com.cn/problem/P3388

【题目描述】
给出一个 n 个点,m 条边的无向图,求图的割点。

【输入格式】
第一行输入两个正整数 n,m。
下面 m 行每行输入两个正整数 x,y,表示 x 到 y 有一条边。

【输出格式】
第一行输出割点个数。
第二行按照节点编号从小到大输出节点,用空格隔开。

【输入样例】
6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6

【输出样例】
1
5

【说明/提示】
对于全部数据,1≤n≤2×10^4,1≤m≤1×10^5。
点的编号均大于 0 小于等于 n。
Tarjan 图不一定连通。

【Tarjan 算法简介】
Tarjan 算法是一种基于深度优先搜索(DFS)的图论算法,由 Robert Tarjan 提出,主要用于求解有向图的强连通分量(SCC),同时也可应用于无向图的桥和割点检测。其核心思想是通过维护两个关键数组(dfn 和 low)及栈结构,实现线性时间复杂度(O(V+E))的求解。
(1)Tarjan算法的两个核心数组 dfn[x] 与 low[x]
dfn[x]‌:节点 x 的 DFS 访问顺序(时间戳)。
low[x]‌:节点 x 能回溯到的最小 dfn 值。
(2)数组 low[x] 的更新规则
● 若 x 是 y 的父节点(即 y 通过 DFS 树边被访问),则 low[x]=min(low[x], low[y])。
作用‌:将子节点 y 能回溯到的最小值传递给父节点 x。
● 若 (x, y) 不是树的边,则 low[x]=min(low[x], dfn[y])。`
作用‌:通过回边直接回溯到祖先节点 y 的 DFS 序。

【算法代码】

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

const int N=2e4+5;
const int M=2e5+5;
int e[M],ne[M],h[N],idx;
int dfn[N],low[N],timestamp;
bool isCut[N];
int ans[N],cnt;

void add(int a,int b) {
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void tarjan(int u,int root) {
    dfn[u]=low[u]=++timestamp;
    int child=0;
    for(int i=h[u]; i!=-1; i=ne[i]) {
        int v=e[i];
        if(!dfn[v]) {
            child++;
            tarjan(v,root);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u] && u!=root) {
                isCut[u]=true;
            }
        } else low[u]=min(low[u],dfn[v]);
    }

    if(u==root && child>=2) {
        isCut[root]=true;
    }
}

int main() {
    memset(h,-1,sizeof h);
    int n,m;
    cin>>n>>m;
    while(m--) {
        int u,v;
        cin>>u>>v;
        add(u,v), add(v,u);
    }

    for(int i=1; i<=n; i++) {
        if(!dfn[i]) tarjan(i,i);
    }

    for(int i=1; i<=n; i++) {
        if(isCut[i]) ans[cnt++]=i;
    }

    cout<<cnt<<endl;
    for(int i=0; i<cnt; i++) {
        cout<<ans[i]<<" ";
    }

    return 0;
}


/*
in:
6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6

out:
1
5
*/

【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/139796863

相关推荐
Jasmine_llq17 天前
《P3825 [NOI2017] 游戏》
算法·游戏·枚举法·2-sat 算法·tarjan 算法·邻接表存储