[洛谷P3388]【模板】割点(割顶)
题目大意:求出一个无向图的割点
题解:$tarjan$,若一个点为根节点(起始节点),只需要判断它有多少个儿子,若不是根节点,假如$low_v\geqslant DFN_v$就说明$v$没有返祖边,即该节点$u$为割点。
卡点:1.多输出了一些数
2.没有去重
C++ Code:
#include <cstdio>
#include <algorithm>
#define maxn 100010
using namespace std;
int n, m;
int ans[maxn], ansnum;
int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
void add(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
}
int DFN[maxn], low[maxn], idx;
inline int min(int a, int b) {return a < b ? a : b;}
void tarjan(int u, int rt) {
DFN[u] = low[u] = ++idx;
int child = 0;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (DFN[v]) low[u] = min(low[u], DFN[v]);
else {
tarjan(v, rt);
low[u] = min(low[u], low[v]);
if (u == rt) child++;
if (u != rt && low[v] >= DFN[u]) {
ans[ansnum++] = u;
}
}
}
if (child >= 2) ans[ansnum++] = u;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
}
for (int i = 1; i <= n; i++) {
if (!DFN[i]) tarjan(i, i);
}
sort(ans, ans + ansnum);
ansnum = unique(ans, ans + ansnum) - ans;
printf("%d\n", ansnum);
for (int i = 0; i < ansnum - 1; i++) printf("%d ", ans[i]);
if (ansnum) printf("%d\n", ans[ansnum - 1]);
return 0;
}

浙公网安备 33010602011771号