题目
思路
(本题是直接给了有向树,所以不用像求树的最大独立集,重心,最长路径这样的无根转有向)
1.状态定义:d(u),让u给上级发信最少需要多少个工人。
2.初状态:
3.答案:d(0)
4.状态转移方程:
(注意此处求c时的小数处理)
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;
const int maxn = 100000 + 100;
int N, T, d[maxn];
vector<int> sons[maxn]; // sons[i]为结点i的儿子们
int dp(int u) {
if (sons[u].empty()) return 1;
vector<int> d;
for (vector<int>::iterator iter = sons[u].begin(); iter != sons[u].end(); ++iter)
d.push_back(dp(*iter));
sort(d.begin(), d.end());
int c = (sons[u].size()*T - 1) / 100 + 1; // 此处的减一加一适合于出现小数的情况
int ans = 0;
_for(i, 0, c) ans += d.at(i);
return ans;
}
int main() {
while (scanf("%d%d", &N, &T) == 2 && N && T) {
int u;
_rep(i, 0, N) sons[i].clear();
_rep(i, 1, N) {
scanf("%d", &u);
sons[u].push_back(i);
}
printf("%d\n", dp(0));
}
return 0;
}