工人的请愿 树形DP uva12186

https://uva.onlinejudge.org/external/121/p12186.pdf

给出一个树状关系图,公司里只有一个老板编号为0,其他人员从1开始编号。除了老板,每个人都有一个直接上司,没有下属的员工成为工人。

工人们想写一份加工资的请愿书,只有当不少于员工的所有下属的T%人递交请愿书后,该员工才会将请愿书递交给他的直接上级。输出能递交到老板处,最少需要多少工人写请愿书

分析:

d(u)表示让u给上级发信最少需要多少个工人。假设u有k个子节点,则至少需要c = (k*T - 1) / 100 + 1 个直接下级发信给他才行。把所有子节点的d从小到大排序,前c个和就是d(u)。而所求答案就是d(0)。

这里考虑到浮点误差,所以才将 k*T / 100 写为 (k*T - 1) / 100 + 1 , 这样一来c就是 不少于k的T%的最小整数。

#include
#include
#include
using namespace std;

const int maxn = 100000 + 5;
int n, T;
vector sons[maxn];

int dp(int u) {
  if(sons[u].empty()) return 1;
  int k = sons[u].size();
  vector d;
  for(int i = 0; i < k; i++)
    d.push_back(dp(sons[u][i]));
  sort(d.begin(), d.end());
  int c = (k*T - 1) / 100 + 1;
  int ans = 0;
  for(int i = 0; i < c; i++) ans += d[i];
  return ans;
}

int main() {
  int f;
  while(scanf("%d%d", &n, &T) == 2 && n) {
    for(int i = 0; i <= n; i++) sons[i].clear();
    for(int i = 1; i <= n; i++) {
      scanf("%d", &f);
      sons[f].push_back(i);
    }
    printf("%d\n", dp(0));
  }
  return 0;
}


你可能感兴趣的:(树形DP)