ARC112C - DFS Game【树】

题意

给定一棵 \(n\) 个点的树,以 \(1\) 为根。开始时,每个节点都有一个硬币,两个人轮流执行以下以下操作:

  • 如果当前节点有硬币,取走硬币,该人的操作结束;
  • 如果当前节点没有硬币,选择该节点一个有硬币的儿子节点,结束本次操作,否则,回到其父亲节点;

求出先手最多可以得到多少个硬币。(\(2\leq n \leq 10^5\))

分析

https://www.cnblogs.com/HotPants/p/14402231.html

代码

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=1e5+5;
vector<int>pic[N];
int f[N],sz[N];
void dfs(int u)
{
    sz[u]=1;
    f[u]=1;
    vector<int>num;
    int sum=0;
    for(auto v:pic[u])
    {
        dfs(v);
        sz[u]+=sz[v];
        if(sz[v]&1) num.pb(f[v]);
        else
        {
            if(f[v]<0) f[u]+=f[v];
            else sum+=f[v];
        }
    }
    sort(num.begin(),num.end());
    num.pb(sum);//
    for(int i=0;i<num.size();i++)
    {
        if(i%2==0) f[u]+=num[i];
        else f[u]-=num[i];
    }
}
int main()
{
    int n,p;
    scanf("%d",&n);
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&p);
        pic[p].pb(i);
    }
    dfs(1);
    printf("%d\n",(f[1]+n)/2);
    return 0;
}
posted @ 2021-02-14 21:46  xzx9  阅读(90)  评论(0编辑  收藏  举报