Uva 12186 - Another Crisis(树形DP)

题目链接 https://cn.vjudge.net/problem/UVA-12186

【题意】
某公司有1个老板和n(n<=1e5)个员工,组成树形结构,除了老板其他员工都有自己的直接上司,老板编号为0,员工为1~n。工人们(没有下属的员工)打算写一份请愿书递交给老板,但是不能跨级传递,只能通过直接上司逐级传递,当一个中级员工的直属下属中不小于T%的人签字时,他也会签字并递给他的直属上司。问题是若要让老板收到请愿书,至少需多少工人签字?

【思路】
紫书282页例题,设d(u)表示让u递交给上级至少需签字多少人,最终答案是d(0). 如果u有k个直接下属,那么先求出所有子结点的d值,然后升序排序取出前ceil(k*T/100)个d值求和即为d(u)的值

#include<bits/stdc++.h>
using namespace std;

const int maxn=100050;

int n,t;
vector<int> g[maxn];
int dp[maxn];

int dfs(int u){
    if(g[u].size()==0) return dp[u]=1;
    if(dp[u]!=-1) return dp[u];
    vector<int> v;
    for(int i=0;i<g[u].size();++i){
        int x=g[u][i];
        v.push_back(dfs(x));
    }
    sort(v.begin(),v.end());
    int ans=0,num=(g[u].size()*t-1)/100+1;
    for(int i=0;i<num;++i) ans+=v[i];
    return dp[u]=ans;
}

int main(){
    while(scanf("%d%d",&n,&t)==2){
        if(0==n && 0==t) break;
        memset(dp,-1,sizeof(dp));
        for(int i=0;i<=n;++i) g[i].clear();
        for(int i=1;i<=n;++i){
            int par;
            scanf("%d",&par);
            g[par].push_back(i);
        }
        int ans=dfs(0);
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2018-04-14 15:09  不想吃WA的咸鱼  阅读(116)  评论(0编辑  收藏  举报