题目链接: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 }