CF1914F Programming Competition
感觉有点类似 agc034e Complete Compress,但那题比这个难得多。
定义 \(f_x\) 为以 \(x\) 为根的子树中,尽可能组队后最多剩下多少人,\(siz_x\) 为子树大小。
记 \(y\in son(x)\) 中 \(f_y\) 最大的点为 \(hson_x\)。
当 \(\sum\limits_{y\in son(x),y\not=hson_x} siz_y < f_{hson_x}\) 时,说明即使其他子树中的人都来跟 \(hson_x\) 子树中的点配对,也无法配对完,还是会剩下 \(f_{hson_x}-\sum\limits_{y\in son(x),y\not=hson_x} siz_y\) 即 \(f_{hson_x}-(siz_x-1-siz_{hson_x})\) 个人。
否则就是尽可能可以配对完,那么这时会剩下 \((siz_x-1)\bmod 2\) 个人。证明考虑每次选出所有剩余 \(f_y\) 中最大的两个,一起 \(-1\),这样就相当于最后只会剩 \(0\sim 1\) 个 \(1\),就等于 \(siz_x-1\) 的奇偶性。
最后要使 \(f_x\) 加上 \(x\) 自己。综上
\(f_x=\begin{cases} f_{hson_x}-(siz_x-1-siz_{hson_x})+1 & f_hson_x>(siz_x-1-siz_{hson_x}) \\ (siz_x-1)\bmod 2 +1 & f_hson_x\leq (siz_x-1-siz_{hson_x}) \end{cases}\)
答案为 \(\dfrac{n-f_{root}}{2}\)。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=2e5+10;
int t,n,fa[MAXN],siz[MAXN],f[MAXN],hson[MAXN];
vector <int> v[MAXN];
void dfs(int x)
{
for(int y:v[x])
{
dfs(y),siz[x]+=siz[y];
if(f[y]>f[hson[x]]) hson[x]=y;
}
if(f[hson[x]]>siz[x]-siz[hson[x]])
f[x]=f[hson[x]]-(siz[x]-siz[hson[x]]);
else f[x]=(siz[x]&1);f[x]+=1,siz[x]+=1;return ;
}
int main()
{
#ifdef ONLINE_JUDGE
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(0);
#endif
cin>>t;
while(t--)
{
cin>>n;
for(int i=2;i<=n;++i)
cin>>fa[i],v[fa[i]].push_back(i);
dfs(1);cout<<(n-f[1])/2<<'\n';
for(int i=1;i<=n;++i)
v[i].clear(),fa[i]=siz[i]=f[i]=hson[i]=0;
}
return 0;
}