UVa12186:Another Crisis(树形DP)

一道简单的树形DP送给你。

A couple of years ago, a new world wide crisis started, leaving many people with economical problems. Some workers of a particular company are trying to ask for an increase in their salaries.

数年以前,人们遭受了世界范围的经济危机。于是某司工人们要求涨薪。(我百度了一下,金融危机应该降薪才对啊~)

The company has a strict hierarchy, in which each employee has exactly one direct boss, with the exception of the owner of the company that has no boss. Employees that are not bosses of any other employee are called workers. The rest of the employees and the owner are called bosses.

除了公司的拥有者之外,每个雇员都仅有一个上司,(此时一个树形的管理体系呈现在你的眼前),管理链末端的雇员叫做工人,其余的叫老板(领导)。

To ask for a salary increase, a worker should ?le a petition to his direct boss. Of course, each boss is encouraged to try to make their subordinates happy with their current income, making the company’s pro?t as high as possible. However, when at least T percent of its direct subordinates have ?led a petition, that boss will be pressured and have no choice but to ?le a petition himself to his own direct boss. Each boss ?les at most 1 petition to his own direct boss, regardless on how many of his subordinates ?led him a petition. A boss only accounts his direct subordinates (the ones that ?led him a petition and the ones that didn’t) to calculate the pressure percentage.

工人想涨薪时需要向他的直系领导提交请愿书。当某位管理,他的直系下属至少T%都给他递请愿书的话,他就别无选择只能也向他的上司请愿。而无论他的手下递给他多少份请愿,他只要递给他的上司一份即可。

Note that a boss can have both workers and bosses as direct subordinates at the same time. Such a boss may receive petitions from both kinds of employees, and each direct subordinate, regardless of its kind, will be accounted as 1 when checking the pressure percentage.

注意有些领导可能直系下属中既有管理层又有普通工人,则一视同仁,每个人只计数为1.

When a petition ?le gets all the way up to the owner of the company, all salaries are increased. The workers’ union is desperately trying to make that happen, so they need to convince many workers to ?le a petition to their direct boss.

现在工会要动员大家请愿,使得请愿书能一直递到终极boss的手上,他就会给涨薪。

Given the company’s hierarchy and the parameter T, you have to ?nd out the minimum number of workers that have to ?le a petition in order to make the owner receive a petition.

会给出T的值,你来计算最少要发动多少工人才能达到目的。

Input
There are several test cases. The input for each test case is given in exactly two lines. The ?rst line contains two integers N and T (1 ≤ N ≤ 105 , 1 ≤ T ≤ 100), separated by a single space. N indicates the number of employees of the company (not counting the owner) and T is the parameter described above. Each of the employees is identi?ed by an integer between 1 and N. The owner is identi?ed by the number 0. The second line contains a list of integers separated by single spaces. The integer Bi, at position i on this list (starting from 1), indicates the identi?cation of the direct boss of employee i (0 ≤ Bi ≤ i?1). The last test case is followed by a line containing two zeros separated by a single space.

每组数据给出两行。第一行是N和T,其中N是公司中不包括公司主在内的雇员个数,T是之前题目中的百分之T。公司雇员从1~N编号,接下来的一行按照从第一个到第N个人的顺序给出此人的上司是谁。

Output
For each test case output a single line containing a single integer with the minimum number of workers that need to ?le a petition in order to get the owner of the company to receive a petition.

每组测试输出一个整数代表最少需要发动的工人数目。

Sample Input
3 100

0 0 0

3 50

0 0 0

14 60

0 0 1 1 2 2 2 5 7 5 7 5 7 5

0 0

Sample Output
3

2

5

提示:前两个样例明确了题目规则,第三个样例通过作图可以想到解题策略。

思路:深搜+排序贪心。对这棵树每一层的子结构都进行贪心选取最小的那几个(具体选几个用T算一下),就可以得到根节点的值。每个工人的值是1,管理层的值是由他对下属(子结构)的选择决定的。

也没什么可说的了,代码中有更具体的注释:

C++11、30ms

 1 #include <bits/stdc++.h>
 2 #define maxn 100005
 3 using namespace std;
 4
 5 int n, T;
 6 vector <int> subordinate[maxn];
 7
 8 int dfs(int boss)
 9 {
10     int person = subordinate[boss].size();
11     if (person == 0)    return 1;//当这个编号的人是工人时直接返回
12
13     vector <int> temp;//储存各个子结构的值
14     for (int i : subordinate[boss])//遍历当前这个人的下属们
15         temp.push_back(dfs(i));
16
17     subordinate[boss].clear();//没用了顺手清空
18
19     sort(temp.begin(), temp.end());//排序以便之后贪心选择最少的几个
20
21     int need = (person * T - 1)/100 + 1;//注意这是一个计算最少要选几个人的技巧
22
23     int sum = 0;
24     for (int i = 0; i < need; i++)    sum += temp[i];
25     return sum;
26 }
27
28 int readboss()//数据量达到了十万,普通版的快速读
29 {
30     int x = 0, s = 1, c = getchar();
31     while (c <= 32)    c = getchar();
32     if (c == ‘-‘)    s = -1, c = getchar();
33     for (; isdigit(c); c = getchar())    x = x*10 + c - 48;
34     return x * s;
35 }
36
37 int main()
38 {
39     while (cin >> n >> T && n && T)
40     {
41         for (int i = 1; i <= n; i++)//储存每个人的直系下属
42             subordinate[readboss()].push_back(i);
43         cout << dfs(0) << endl;
44     }
45 }

原文地址:https://www.cnblogs.com/AlphaWA/p/9614143.html

时间: 2024-10-17 05:43:56

UVa12186:Another Crisis(树形DP)的相关文章

uva 12186 Another Crisis 树形dp

// uva 12186 Another Crisis 树形dp // // 对于一个节点u,有k个子节点,则至少有c = (k * T - 1) / 100 + 1才能 // 发信,即c / k >= T / 100,则 c 的值为 k * T /100,上取整变成上式 // 将所有的子节点d从小到大排序,取前c个就是d[u]的值 // 紫书上的一题,之前看了好久好久,觉得挺好的,然而一直没做,今天就来 // 体验体验,挺好的一题,注意一下,如果一个节点是叶节点,直接return 1就好 //

UVA12186--- Another Crisis (树形dp)

Description Download as PDF A couple of years ago, a new world wide crisis started, leaving many people with economical problems. Some workers of a particular company are trying to ask for an increase in their salaries. The company has a strict hiera

UVA 12186 Another Crisis(树形DP)

A couple of years ago, a new world wide crisis started, leaving many people with economical problems. Some workers of a particular company are trying to ask for an increase in their salaries. The company has a strict hierarchy, in which each employee

uva 1220 - Party at Hali-Bula 【入门树形dp】

题目:uva 1220 - Party at Hali-Bula 题意:一个公司员工要举行聚会,要求任意一个人不能和他的直接上司同时到场,一个员工只有一个支系上司,现在求最多有多少人到场,并且方案是否唯一 分析:分析发现是要求一个树的最大独立集.这里可以用树形dp解决. 定义dp[x][0]:表示在 i 点不选 i 点的以 x 为子树的最大独立集 而dp[x][1] 表示x到场的最大独立集 定义f [x][0]:表示以x为根且x点不选的子树是否唯一 ,f[x][1]表示以x为根且x选的子树是否唯

HDU-2196 Computer (树形DP)

最近在看树形DP,这题应该是树形DP的经典题了,写完以后还是有点感觉的.之后看了discuss可以用树分治来做,以后再试一试. 题目大意 找到带权树上离每个点的最远点.︿( ̄︶ ̄)︿ 题解: 对于每一个点的最远点,就是以这个点为根到所有叶子节点的最长距离.但是如果确定根的话,除了根节点外,只能找到每个节点(度数-1)个子树的最大值,剩下一个子树是该节点当前的父亲节点. 所以当前节点的最远点在当前节点子树的所有叶子节点以及父亲节点的最远点上(当父亲节点的最远点不在当前节点的子树上时), 如果父亲节

UVA-01220 Party at Hali-Bula (树形DP+map)

题目链接:https://vjudge.net/problem/UVA-1220 思路: 树形DP模板题,求最大人数很简单,难点在于如何判断最大人数的名单是否有不同的情况: 解决方法是用一个数组f[manx][2]记录该节点是否出场的情况,为真时代表有多种情况; 具体讨论: 当父节点的值加上某个子节点的值时,他的f的情况也和该子节点一样: 当某个节点dp(i, 0) == dp(i, 1), 则该节点以及它的父节点也一定有多种情况(父节点必定取其中之一). Code: 1 #include<bi

HDU 1520 树形dp裸题

1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b using nam

HDU2196 Computer(树形DP)

和LightOJ1257一样,之前我用了树分治写了.其实原来这题是道经典的树形DP,感觉这个DP不简单.. dp[0][u]表示以u为根的子树中的结点与u的最远距离 dp[1][u]表示以u为根的子树中的结点与u的次远距离 这两个可以一遍dfs通过儿子结点转移得到.显然dp[0][u]就是u的一个可能的答案,即u往下走的最远距离,还缺一部分就是u往上走的最远距离: dp[2][u]表示u往上走的最远距离 对于这个的转移,分两种情况,是这样的: dp[2][v] = max( dp[0][u]+w

hdu5593--ZYB&#39;s Tree(树形dp)

问题描述 ZYB有一颗N个节点的树,现在他希望你对于每一个点,求出离每个点距离不超过KK的点的个数. 两个点(x,y)在树上的距离定义为两个点树上最短路径经过的边数, 为了节约读入和输出的时间,我们采用如下方式进行读入输出: 读入:读入两个数A,B,令fai??为节点i的父亲,fa?1??=0;fa?i??=(A∗i+B)%(i−1)+1,i∈[2,N] . 输出:输出时只需输出N个点的答案的xor和即可. 输入描述 第一行一个整数TT表示数据组数. 接下来每组数据: 一行四个正整数N,K,A,