CF1914F Programming Competition

发布时间 2023-12-20 11:25:31作者: int_R

原题链接

感觉有点类似 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;
}