tarjan eDCC

Tarian 一遍,标记割边。记录 eDCC(边双联通分量)将 eDCC 缩点。 得到一棵树,树边就是原图的割边。
观察发现.最少需要加(sum+1)/2条边.可以使整个图变为边的双连通图。sum 为缩点后叶节点的个数。

板子

int dfn[N], low[N], tim, dcc[N], cnt, bri[M], du[N];
stack<int> s;

void tarjan(int x, int fa)
{
	dfn[x] = low[x] = ++tim;
	s.push(x);
	for (int i = head[x]; i; i = nxt[i])
	{
		int y = to[i];
		if (!dfn[y])
		{ // 若y尚未访问
			tarjan(y, i);
			low[x] = min(low[x], low[y]);
			if (dfn[x] < low[y])
				bri[i] = bri[i ^ 1] = 1; // 桥
		}
		else if (i != (fa ^ 1)) // 不是反边
			low[x] = min(low[x], dfn[y]);
	}
	if (dfn[x] == low[x])
	{
		++cnt;
		while (1)
		{
			int y = s.top();
			s.pop();
			dcc[y] = cnt; // eDCC
			if (y == x)
				break;
		}
	}
}
int main()
{
	cin >> n >> m;
	while (m--)
	{
		cin >> x >> y;
		add(x, y), add(y, x);
	}
	tarjan(1, 0);
	for (int i = 2; i <= tot; i++)
		if (bri[i])
			du[dcc[to[i]]]++; // 度数
	for (int i = 1; i <= cnt; i++)
		if (du[i] == 1)
			sum++; // 叶节点数
	printf("%d\n", (sum + 1) / 2);
	return 0;
}
posted @ 2025-02-26 19:30  流氓兔LMT  阅读(16)  评论(0)    收藏  举报