P3388 【模板】割点(割顶)题解 tarjan求割点

题目链接:https://www.luogu.com.cn/problem/P3388

参考博客:http://keyblog.cn/article-80.html

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 20020, maxm = 200020;
struct Edge {
    int v, nxt;
    Edge() {};
    Edge(int _v, int _nxt) { v = _v; nxt = _nxt; }
} edge[maxm];
int n, m, ecnt, head[maxn];
void init() {
    memset(head, -1, sizeof(int)*(n+1));
}
void addedge(int u, int v) {
    edge[ecnt] = Edge(v, head[u]); head[u] = ecnt ++;
    edge[ecnt] = Edge(u, head[v]); head[v] = ecnt ++;
}
int num, dfn[maxn], low[maxn], rt;
bool point[maxn];
void tarjan(int u, int p) {
    dfn[u] = low[u] = ++ num;
    int son = -1;
    for (int i = head[u]; i != -1; i = edge[i].nxt) {
        int v = edge[i].v;
        if (v == p) continue;
        if (!dfn[v]) {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (u != rt && dfn[u] <= low[v])
                point[u] = true;
            if (son == -1) son = v;
            else if (son != v) son = -2;
        }
        else low[u] = min(low[u], dfn[v]);
    }
    if (u == rt && son == -2) point[u] = true;
}
int main() {
    cin >> n >> m;
    init();
    while (m --) {
        int u, v;
        cin >> u >> v;
        addedge(u, v);
    }
    for (int i = 1; i <= n; i ++) {
        if (!dfn[i]) {
            rt = i;
            tarjan(i, -1);
        }
    }
    int cnt = 0;
    for (int i = 1; i <= n; i ++) if (point[i]) cnt ++;
    cout << cnt << endl;
    for (int i = 1; i <= n; i ++) if (point[i]) cout << i << " ";
    return 0;
}
posted @ 2020-05-18 01:35  quanjun  阅读(151)  评论(0编辑  收藏  举报