[关闭]
@ZCDHJ 2019-08-09T03:08:12.000000Z 字数 1240 阅读 514

ARC083E Bichrome Tree

未分类


的子树中所有点对 的父亲的贡献在颜色相同时是 ,颜色不相同时是 的子树和。发现只要所有子树的贡献不超过 结点可以随便填一个数来满足限制。那么贪心的想就是要所有子树能够造成的贡献最小也就是 最小。因为一棵子树内所有点的相对颜色已经确定,再怎么翻转也不影响本来的答案,所以两种情况可以直接枚举,做一遍 DP 将所有的贡献可能算出来,取一个最大且不超过 的即是最优的决策,此时 最小。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cstdlib>
  5. const int MAXN = 1000;
  6. int n, edge;
  7. int X[MAXN | 1], fst[MAXN | 1];
  8. int sum[MAXN | 1], dp[MAXN | 1][5001];
  9. struct Edge {
  10. int to, nxt;
  11. Edge() : to(0), nxt(0) {}
  12. Edge(int a, int b) : to(b), nxt(fst[a]) {}
  13. } e[MAXN];
  14. inline int read() {
  15. register int x = 0;
  16. register char ch = getchar();
  17. while (!isdigit(ch)) ch = getchar();
  18. while (isdigit(ch)) {
  19. x = x * 10 + ch - '0';
  20. ch = getchar();
  21. }
  22. return x;
  23. }
  24. inline void addEdge(int a, int b) {
  25. e[++edge] = Edge(a, b);
  26. fst[a] = edge;
  27. }
  28. void DP(int x) {
  29. int size = 0;
  30. for (int k = fst[x]; k; k = e[k].nxt) {
  31. int to = e[k].to;
  32. DP(to);
  33. sum[x] += sum[to];
  34. ++size;
  35. }
  36. memset(dp, 0, sizeof(dp));
  37. dp[0][0] = 1;
  38. for (int i = 1, k = fst[x]; k; k = e[k].nxt, ++i) {
  39. int to = e[k].to;
  40. for (int j = 0; j <= X[x]; ++j) {
  41. if (j >= X[to]) dp[i][j] |= dp[i - 1][j - X[to]];
  42. if (j >= sum[to] - X[to]) dp[i][j] |= dp[i - 1][j - sum[to] + X[to]];
  43. }
  44. }
  45. bool flag = false;
  46. for (int i = X[x]; i >= 0; --i) {
  47. if (dp[size][i]) {
  48. flag = true;
  49. sum[x] += X[x] - i;
  50. break;
  51. }
  52. }
  53. if (!flag) {
  54. puts("IMPOSSIBLE");
  55. exit(0);
  56. }
  57. }
  58. int main() {
  59. n = read();
  60. for (int i = 2; i <= n; ++i) addEdge(read(), i);
  61. for (int i = 1; i <= n; ++i) X[i] = read();
  62. DP(1);
  63. puts("POSSIBLE");
  64. return 0;
  65. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注