zoukankan      html  css  js  c++  java
  • [POI2013]LUK-Triumphal arch

    • 由于syk大佬表示POI都是好题,于是我(被syk大佬一路暴踩后)来水水题解

    • 题意

    给一颗树,1号节点已经被染黑,其余是白的,两个人轮流操作,一开始B在1号节点,A选择k个点染黑,然后B走一步,如果B能走到A没染的节点则B胜,否则当A染完全部的点时,A胜。求能让A获胜的最小的k

    • solution

    二分答案,树形DP,首先二分k,将问题转化为判定性问题
    然后记DP[x]为在x的子树内博弈时,至少还要多染几个点才能使A赢
    明显DP[x]=max(sum(DP[to]+1)-k,0)这里to是x的儿子
    然后只要DP[1]=0则可行
    然后就做完了

    • code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #define N 2000100
    using namespace std;
    vector<int> v[N];
    int dp[N];
    int l,r,mid,n,ans;
    void dfs(int x,int fa){
        dp[x]=0;
        for(int i=0;i<v[x].size();i++){
            int to=v[x][i];
            if(to==fa)continue;
            dfs(to,x);
            dp[x]+=dp[to]+1;//状态转移1
        }
        dp[x]=max(dp[x]-mid,0);//状态转移2
    }
    bool check(int t){
      dfs(1,0);
      return dp[1]==0;
    }
    int main(){
    scanf("%d",&n);
    if(n==1){cout<<0;return 0;}
    for(int i=1;i<n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        v[a].push_back(b),v[b].push_back(a);
    }
    l=1,r=n;
    while(l<=r){
        mid=(l+r)>>1;
        if(check(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    printf("%d
    ",ans);
    }
    
  • 相关阅读:
    类和对象
    类和对象1
    常见的子串问题
    常见的算法问题全排列
    第六届蓝桥杯java b组第五题
    第六届蓝桥杯java b组第四题
    第六届蓝桥杯java b组第三题
    第六届蓝桥杯java b组第二题
    第六届蓝桥杯java b组第一题
    第八届蓝桥杯java b组第三题
  • 原文地址:https://www.cnblogs.com/stepsys/p/11587065.html
Copyright © 2011-2022 走看看