--- 这里是 cjiaw 的小窝(●'◡'●) ---

正在玩命加载中......

洛谷__P3388 【模板】割点(割顶)

题目链接:P3388 【模板】割点(割顶) - 洛谷


题目描述:

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


割点:

在图上删除一个点后变为不连通,(从一整块变成两块以上...)


代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<bitset>
#include<tuple>
#define inf 9187201950435737471
#define int long long
#define endl '\n'
#define F first
#define S second
using namespace std;
typedef pair<int, int> pii;

const int N = 20086, M = 200086;

int n, m, root;
int h[N], ne[M], e[M], idx;
int dfn[N], low[N], ti;
stack<int> st;
bool cut[N];
set<int> res;

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


void tarjan(int u) {

    dfn[u] = low[u] = ++ti;
    
    int cnt = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (!dfn[j]) {
            cnt++;
            tarjan(j);
            low[u] = min(low[u], low[j]);
            
            if (dfn[u] <= low[j] && root != u) res.insert(u);
            if (u == root && cnt >= 2) res.insert(u);

        } else low[u] = min(low[u], dfn[j]);
        
    }
    
}

void solve() {
    memset(h, -1, sizeof h);
    cin >> n >> m;
    while (m--) {
        int a, b;
        cin >> a >> b;
        if (a == b) continue;
        add(a, b), add(b, a);
    }
    
    for (root = 1; root <= n; root++) {
        if (!dfn[root]) tarjan(root);
    }
    
    cout << res.size() << endl;
    for (auto x : res) cout << x << " ";
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    
    int T = 1;
// cin >> T;
    while (T--) solve();
    
    return 0;
}

 

posted @ 2025-10-27 23:22  wwjjw  阅读(23)  评论(0)    收藏  举报