UVA12186 (树形DP)

题意:一个老板和n个员工组成树状结构,每个员工都有自己的唯一上司,老板的编号为0,员工1~n,工人们打算签署一个志愿书给老板,但无法跨级,当一个中级员工(非是工人的员工)的直属下属中不小于T%的人签字时,他也会签字并且递给他的直属上司,问:要让老板收到请愿书至少需要多少个工人签字。

注意:这里要求的是最底层工人(即叶子结点)的最少个数。

思路:从0dfs,自底向上,对每一个结点当做跟来排序他的孩子(按ans数从小到大),然后计算至少需要多少个孩子,再往上一层传递,典型的树形DP。

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=100005;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
vector<int> v[maxn];
int n,t;
int dfs(int u)
{
    if(v[u].empty())
        return 1;
    vector<int> d;
    for(int i=0;i<v[u].size();i++)
    {
        d.push_back(dfs(v[u][i]));
    }
    sort(d.begin(),d.end());
    int c=v[u].size()*t;
    if(c%100)
    {
        c=c/100+1;
    }
    else
        c=c/100;
    int ans=0;
    for(int i=0;i<c;i++)
    {
        ans+=d[i];
    }
    return ans;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    while(cin>>n>>t)
    {
        if(!n&&!t)
        {
            break;
        }
        for(int i=0;i<maxn;i++)
        {
            v[i].clear();
        }
        for(int i=1;i<=n;i++)
        {
            int a;
            cin>>a;
            v[a].push_back(i);
        }
        cout<< dfs(0) <<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dilly__dally/article/details/82254940
今日推荐