题目大意:求出一个无向图的割点
题解:$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; }
原文:https://www.cnblogs.com/Memory-of-winter/p/9525310.html