AtCoder Beginner Contest 246 G Game on Tree 3

 首先二分是比较明显的,二分答案val看Takahashi在游戏中是否能取到大于等于val的值,也就是Aoki要在Takahashi在到达每个点大于等于val的点前将那个点清空,我们使用DP来解决,dp[x]表示如果Takahashi从x出发,那么在游戏开始前,Aoki至少需要清空dp[x]个点才能让Takahashi达不到大于等于val的值,那么显然dp[x]=max(0,sum(dp[vi])-1),其中vi为x的子节点,如果dp[x]本身就大于等于val,则显然dp[x]需要再加一,最后如果dp[1]==0则Aoki胜利否则Takahashi胜利

 这道题我没有想到怎么设dp状态,下面是具体代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<queue>
#define maxn 400009 
using namespace std;
int cnt,n,maxd,h[maxn],dp[maxn],a[maxn],b[maxn]; 
struct edge{
    int to;
    int nex;
}edge[maxn];
void adde()
{
    int x,y;
    cin>>x>>y;
    edge[++cnt].to=y; edge[cnt].nex=h[x]; h[x]=cnt;
    edge[++cnt].to=x; edge[cnt].nex=h[y]; h[y]=cnt;
}
void dfs(int x,int fa,int val)
{ 
    //cout<<x<<"!"<<fa<<" "<<dep<<endl;
    bool now=false;
    for (int i=h[x];i;i=edge[i].nex)
    {
        int to=edge[i].to;
        if (to==fa) continue;
        dfs(to,x,val);    
        dp[x]+=dp[to];
        now=true;    
    }
    dp[x]=max(0,dp[x]-1);
    dp[x]+=a[x]>=val?1:0;
//    cout<<x<<"!"<<dp[x]<<endl; 
}
bool check(int val)
{
    for (int i=1;i<=n;i++) dp[i]=0;
    dfs(1,0,val);
    return dp[1]==0?false:true;
}
int main()
{
//dp[x] represents the less number of vertex to change before moving 
    cin>>n;
    a[1]=0;
    for (int i=2;i<=n;i++) cin>>a[i],b[i]=a[i];
    for (int i=1;i<n;i++) adde();
    sort(b+1,b+1+n);
    int l=1,r=n,ans=0;
    while (l<=r)
    {
        int mid=(l+r)>>1;
        //cout<<l<<" "<<r<<" "<<b[mid]<<endl;
        if (check(b[mid])) l=mid+1,ans=mid;
        else r=mid-1;
    }
    cout<<b[ans]<<endl;    
    return 0;
}

 

posted on 2022-04-08 16:37  nhc2014  阅读(37)  评论(0编辑  收藏  举报