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

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

 

【模板】割点(割顶)

题目背景

割点

题目描述

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

输入格式

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

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

输出格式

第一行输出割点个数。

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

样例 #1

样例输入 #1

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

样例输出 #1

1 
5

提示

对于全部数据,$1\leq n \le 2\times 10^4$,$1\leq m \le 1 \times 10^5$。

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

tarjan图不一定联通。

关于割点不会的同学可参考OI-Wiki:https://oi-wiki.org/graph/cut/

模板代码:

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<vector>
  4 #include<map>
  5 #include<queue>
  6 #include<set>
  7 #include<algorithm>
  8 #include<stack>
  9 #include<cmath>
 10 #include<cstring>
 11 #include<string>
 12 using namespace std;
 13 #define gc getchar()
 14 #define rd(x) read(x)
 15 #define el '\n'
 16 #define rep(i, a, n) for(int i = (a); i <= n; ++i)
 17 #define per(i, a, n) for(int i = (a); i >= n; --i)
 18 using ll = long long;
 19 using db = double;
 20 using ldb = long double;
 21 const int mod = 1e9 + 7;
 22 const int inf = 0x3f3f3f3f;
 23 const int N = 2e4 + 10;
 24 
 25 template <typename _T>
 26 inline void read(_T & f) {
 27     f = 0; _T fu = 1; char c = gc;
 28     while (c < '0' || c > '9') { if (c == '-') { fu = -1; } c = gc; }
 29     while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = gc; }
 30     f *= fu;
 31 }
 32 
 33 template <typename T>
 34 void print(T x) {
 35     if (x < 0) putchar('-'), x = -x;
 36     if (x < 10) putchar(x + 48);
 37     else print(x / 10), putchar(x % 10 + 48);
 38 }
 39 
 40 template <typename T>
 41 void print(T x, char t) {
 42     print(x); putchar(t);
 43 }
 44 
 45 struct node {
 46     int to, next;
 47 }e[N << 4];
 48 
 49 int head[N << 4], tot;
 50 
 51 void add(int u,int v) {
 52     e[tot].to = v;
 53     e[tot].next = head[u];
 54     head[u] = tot++;
 55 }
 56 
 57 int vis[N], dfn[N], low[N], cnt, flag[N];
 58 int res = 0;
 59 
 60 void tarjan(int u,int fa) {
 61     vis[u] = 1;
 62     dfn[u] = low[u] = ++cnt;
 63     int child = 0;
 64     for(int i = head[u]; i + 1; i = e[i].next) {
 65         int v = e[i].to;
 66         if(!vis[v]) {
 67             child++;
 68             tarjan(v, u);
 69             low[u] = min(low[u], low[v]);
 70             if(fa != u && low[v] >= dfn[u] && !flag[u]) {
 71                 flag[u] = 1;
 72                 res++;
 73             }
 74         }else if(v != fa) {
 75             low[u] = min(low[u], dfn[v]);
 76         }
 77     }
 78     if(u == fa && child >= 2 && !flag[u]) {
 79         flag[u] = 1;
 80         res++;
 81     }
 82 
 83     return;
 84 }
 85 
 86 int main() {
 87 
 88     int n, m;
 89     cin >> n >> m;
 90     memset(head, -1, sizeof(head));
 91     
 92     for(int i = 1; i <= m; i++) {
 93         int u, v;
 94         cin >> u >> v;
 95         add(u, v),add(v, u);
 96     }
 97     for(int i = 1; i <= n; i++) {
 98         if(!vis[i]) {
 99             cnt = 0;
100             tarjan(i, i);
101         }
102     }
103     cout << res << el;
104     for(int i = 1; i <= n; i++) {
105         if(flag[i]) {
106             cout << i << ' ';
107         }
108     }
109 
110     return 0;
111 }

 

 

 

 
 
posted @ 2022-10-03 10:40  Keyzee  阅读(38)  评论(0编辑  收藏  举报