题解:P4572 [JSOI2013] 哈利波特与死亡圣器

posted on 2024-12-12 10:42:21 | under | source

具有单调性,二分答案 \(k\),考虑判定。

可以发现,伏地魔是不会走回头路的。设当前点 \(u\) 的父亲是 \(fa\),则当伏地魔先前在 \(fa\) 处时肯定是不存在一个未被保护的相邻节点,不然走过去就赢了。那从 \(u\to fa\) 再走到另一个节点肯定不如在 \(fa\) 时直接向那个点走去,因为被保护的点肯定更多了。同时,假如伏地魔走到了 \(u\),那么接下来我们只会对 \(u\) 子树内的点进行保护。

无后效性可以树形 dp。考虑 \(f_u\) 表示伏地魔在 \(u\) 点出发向子树内走去,若要成功防御则至少还需要提前保护多少个点。转移是容易的,\(f_u\gets \max(0,(\sum\limits_{v\in son} 1+f_v)-k)\),因为我们在伏地魔行动前操作,而无法得知他具体往哪走,所以必须让每个儿子子树都合法。

复杂度 \(O(n\log n)\)

闲话:是因为题目名字有趣所以开的这道题,感觉比较水,顶多评个蓝吧。

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 3e5 + 5;
int n, u, v, k, f[N];
vector<int> to[N];

inline void dfs(int u, int fa){
	f[u] = 0;
	for(auto v : to[u])
		if(v ^ fa) dfs(v, u), f[u] += 1 + f[v];
	f[u] = max(0, f[u] - k); 
}
signed main(){
	cin >> n;
	for(int i = 1; i < n; ++i) scanf("%d%d", &u, &v), to[u].push_back(v), to[v].push_back(u);
	int L = -1, R = n, mid;
	while(L + 1 < R){
		mid = (L + R) >> 1;
		k = mid, dfs(1, 0);
		if(!f[1]) R = mid;
		else L = mid;
	}
	cout << R;
	return 0;
}
posted @ 2026-01-15 08:18  Zwi  阅读(3)  评论(0)    收藏  举报