备战NOIP——模板复习23
这里只有模板,并不作讲解,仅为路过的各位做一个参考以及用做自己复习的资料,转载注明出处。
割点
/*Copyright: Copyright (c) 2018
*Created on 2018-11-07
*Author: 十甫
*Version 1.0
*Title: 割点
*Time: inf mins
*/
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 20005;
const int maxm = 100005;
inline int Min(int a, int b) {
return a < b ? a : b;
}
int head[maxn];
struct edge {
int to, next;
} data[maxm * 2];
inline void add_edge(int from, int to, int i) {
data[i] = (edge) {to, head[from]};
head[from] = i;
}
int n, m, dfn[maxn], low[maxn];
bool cut_vertex[maxn];
void dfs(int pos, int &ord, int from) {
dfn[pos] = low[pos] = ord;
int child = 0;
for(int i = head[pos];i;i = data[i].next) {
int u = data[i].to;
if(!dfn[u]) {
dfs(u, ++ord, pos);
low[pos] = Min(low[pos], low[u]);
if(low[u] >= dfn[pos] && pos != from) {
cut_vertex[pos] = true;
}
if(pos == from) {
child++;
}
}
low[pos] = Min(low[pos], dfn[u]);
}
if(pos == from && child >= 2) {
cut_vertex[pos] = true;
}
}
void tarjan() {
for(int i = 1;i <= n;i++) if(!dfn[i]) {
int ord = 1;
dfs(i, ord, i);
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1;i <= m;i++) {
int a, b;
scanf("%d%d", &a, &b);
add_edge(a, b, i), add_edge(b, a, i + m);
}
tarjan();
int cnt = 0;
for(int i = 1;i <= n;i++) if(cut_vertex[i]) {
cnt++;
}
printf("%d\n", cnt);
for(int i = 1;i <= n;i++) if(cut_vertex[i]) {
printf("%d ", i);
}
printf("\n");
return 0;
}
NOIP 2018 RP++