「AGC034E」 Complete Compress

「AGC034E」 Complete Compress

显然可以枚举根。

然后把某两棵棋子同时往深度浅的方向提,即对不存在祖先关系的两个棋子进行操作。

如果能到达那么就更新答案。

问题转化为如何判定能够到达。

考虑对于某一个节点,合法的条件是什么。

(f_u) 为以 (u) 为根的子树中的棋子还需要移动多少步,容易发现对于节点 (u) 的所有孩子 (v),若存在一个 (x)(f_x>(sum f_v)-f_x),那么 (f_x) 一定不能移动完。

然后根据这个东西随便 ( exttt{DP}) 转移一下就行。

似乎存在更优秀的做法。

/*---Author:HenryHuang---*/
/*---Never Settle---*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
char s[maxn];
int w[maxn],dep[maxn];
int f[maxn],siz[maxn];
vector<int> e[maxn];
void dfs(int u,int fa){
	dep[u]=dep[fa]+1;dep[u]=f[u]=0,siz[u]=w[u];
	int son=0;
	for(auto v:e[u]){
		if(v==fa) continue;
		dfs(v,u);
		siz[u]+=siz[v];dep[u]+=dep[v];
		if(f[v]>f[son]) son=v;
	}
	f[u]=(f[son]<=dep[u]-dep[son]?dep[u]&1:f[son]-(dep[u]-dep[son]));
	dep[u]+=siz[u],f[u]+=siz[u];
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int n;cin>>n;
	cin>>(s+1);
	for(int i=1;i<=n;++i) w[i]=s[i]-'0';
	for(int i=1;i<n;++i){
		int a,b;cin>>a>>b;
		e[a].emplace_back(b);
		e[b].emplace_back(a);
	}
	int ans=998244353;
	for(int i=1;i<=n;++i){
		dep[0]=-1;
		dfs(i,0);
		if(f[i]==siz[i]) ans=min(ans,(dep[i]-siz[i])/2);
	}
	if(ans==998244353) cout<<-1<<'
';
	else cout<<ans<<'
';
	return 0;
}
在繁华中沉淀自我,在乱世中静静伫立,一笔一划,雕刻时光。
原文地址:https://www.cnblogs.com/HenryHuang-Never-Settle/p/solution-AGC034E.html