AtCoder [ARC205D] Non-Ancestor Matching 题解

首先有一个很显然但是有用的话,就是如果一个子树内可以进行 \(x\) 次操作,那么这个子树内也可以只进行 \([0,x-1]\) 次操作。

\(\operatorname{dfs}\),设 \(\operatorname{dfs(u)}\) 返回值为在根为 \(u\) 的子树,那么最终答案为 \(\operatorname{dfs(1)}\),接下来考虑如何计算。

\(\operatorname{sons_u}\) 为节点 \(u\) 的儿子集合,\(\operatorname{siz_u}\) 为以节点 \(u\) 为根的子树大小。\(\operatorname{zson}\)\(u\) 的重儿子,\(\operatorname{Max}\)\(\operatorname{siz_{zson}}\)\(\operatorname{sum}=\operatorname{siz_u} - 1\)

对于一棵以 \(u\) 为根的子树:

  1. 如果 \(\operatorname{Max} \leq \operatorname{sum} - \operatorname{Max}\),那么一定有一种方式可以对这棵子树操作 \(\lfloor \dfrac{\operatorname{sum}-1}{2} \rfloor\) 次。
  2. 递归进入 \(\operatorname{zson}\),求出 \(\operatorname{dfs(zson)}\),记作 \(\operatorname{res}\)。 如果 \(\operatorname{Max} - 2 \times \operatorname{res} \leq \operatorname{sum} - \operatorname{Max}\),那么我们就可以先对以 \(\operatorname{zson}\) 为根的子树操作一定次数,操作后可以达到第一种情况,所以返回 \(\lfloor \dfrac{\operatorname{sum}-1}{2} \rfloor\)。否则操作次数仍然只能被 \(\operatorname{zson}\) 限制,那么 \(\operatorname{res}\) 次操作肯定是全要用的,返回 \(\min(\operatorname{Max}-2\times \operatorname{res},\operatorname{sum}-\operatorname{Max})+\operatorname{res}\)
#include <bits/stdc++.h>

using namespace std;

#define int long long
#define endl '\n'

int T, n, siz[500005];
vector <int> sons[500005];
void siz_(int u) {
	siz[u] = 1;
	for (int i = 0; i < sons[u].size(); i++) {
		int v = sons[u][i];
		siz_(v); siz[u] += siz[v];
	}
}
int dfs(int u) {
	int sum = siz[u] - 1, Max = 0, zson;
	for (int i = 0; i < sons[u].size(); i++) {
		int v = sons[u][i];
		if (Max < siz[v]) Max = siz[v], zson = v;
	}
	if (!sons[u].size()) return 0;
	if (Max > sum - Max) {
		int res = dfs(zson);
		if (Max - 2 * res <= sum - Max) return (sum / 2);
		else return min(Max - res, sum - Max + res);
	}
	else return (sum / 2);
}
void solve() {
	cin >> n;
	for (int i = 1; i <= n; i++) 
		sons[i].clear();
	for (int i = 2; i <= n; i++) {
		int u; cin >> u;
		sons[u].push_back(i);
	}
	siz_(1);
	cout << dfs(1) << endl;
}

signed main() {
	std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> T;
	while (T--) solve();
	return 0;
}
posted @ 2025-09-10 23:24  wwqwq  阅读(10)  评论(0)    收藏  举报