首页 > 其他分享 >P6591 [YsOI2020]植树

P6591 [YsOI2020]植树

时间:2023-01-30 20:46:41浏览次数:47  
标签:sz YsOI2020 int dfs P6591 dfs1 植树 push maxn

树上操作太薄弱了,根本想不出来。

思路:

首先自定义根做一遍dfs,求出sz数组,sz[i]表示i的子树大小。

在做第二遍dfs,对每一个点进行尝试,看能否为根。

当 x 点为根转移到 y 点为根时,sz发生变化,

sz[x] -= sz[y]

sz[y] += n - sz[y]

然后进行下一步搜索,回溯时改回来就好。

这道题也体现了dfs的妙处,就是回溯处理问题

#include <bits/stdc++.h>

using namespace std;
const int maxn = 2000005;
int n, sz[maxn];
vector<int>e[maxn];
priority_queue<int>q;
void dfs1(int u, int f)
{
	sz[u] = 1;
	for (int v : e[u]) {
		if (v == f) continue;
		dfs1(v, u);
		sz[u] += sz[v];
	}
}
void dfs2(int u, int f)
{
	// 思路:检验当前点能否为根;再换根搜索邻接点
	bool flg = 0;
	int t = sz[e[u][0]];
	for (int v : e[u]) {
		if (sz[v] != t) {
			flg = 1;
			break;
		}
	}
	if (!flg) {
		q.push(-u);
	}
	for (int v : e[u]) {
		if (v == f) continue;
		// change root
		sz[u] -= sz[v];
		sz[v] += sz[u];
		dfs2(v, u);
		sz[v] -= sz[u];
		sz[u] += sz[v];
	}
}
int main()
{
	scanf("%d", &n);
	if (n == 1) {
	    puts("1");
	    return 0;
	}
	for (int i = 1, a, b; i < n; i++) {
		scanf("%d%d", &a, &b);
		e[a].push_back(b);
		e[b].push_back(a);
	}
	dfs1(1, 0);
	dfs2(1, 0);
	while (q.size()) {
		printf("%d ", -q.top());
		q.pop();
	}
	printf("\n");
	return 0;
}

标签:sz,YsOI2020,int,dfs,P6591,dfs1,植树,push,maxn
From: https://www.cnblogs.com/CYLSY/p/17077191.html

相关文章