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;
}