[洛谷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;
}

 

posted @ 2018-08-23 17:51  Memory_of_winter  阅读(172)  评论(0编辑  收藏  举报