• AcWing 287. 积蓄程度,《算法竞赛进阶指南》


    287. 积蓄程度 - AcWing题库

    有一个树形的水系,由 N−1 条河道和 N 个交叉点组成。

    我们可以把交叉点看作树中的节点,编号为 1∼N,河道则看作树中的无向边。

    每条河道都有一个容量,连接 x 与 y 的河道的容量记为 c(x,y)。

    河道中单位时间流过的水量不能超过河道的容量。

    有一个节点是整个水系的发源地,可以源源不断地流出水,我们称之为源点。

    除了源点之外,树中所有度数为 11 的节点都是入海口,可以吸收无限多的水,我们称之为汇点。

    也就是说,水系中的水从源点出发,沿着每条河道,最终流向各个汇点。

    在整个水系稳定时,每条河道中的水都以单位时间固定的水量流向固定的方向。

    除源点和汇点之外,其余各点不贮存水,也就是流入该点的河道水量之和等于从该点流出的河道水量之和。

    整个水系的流量就定义为源点单位时间发出的水量。

    在流量不超过河道容量的前提下,求哪个点作为源点时,整个水系的流量最大,输出这个最大值

    输入格式

    输入第一行包含整数 T,表示共有 T 组测试数据

    每组测试数据,第一行包含整数 N。

    接下来 N−1行,每行包含三个整数 x,y,z,表示 x,y 之间存在河道,且河道容量为 z�。

    节点编号从 1 开始。

    输出格式

    每组数据输出一个结果,每个结果占一行。

    数据保证结果不超过 2^31−1

    数据范围

    N≤2×105

    输入样例:
    1. 1
    2. 5
    3. 1 2 11
    4. 1 4 13
    5. 3 4 5
    6. 4 5 10
    输出样例:
    26

    解析 :二次扫描与换根法

    这道题目的标签为树形dp,但我觉得它更像是记忆化搜索

    第一次记录仪当前点为根节点的子树的流量

    第二次记录仪当前点为根节点的整棵树的流量

    最后取最大值

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. using namespace std;
    16. typedef long long LL;
    17. const int N = 2e5 + 5, M = 2 * N, INF = 0x3f3f3f3f;
    18. int n;
    19. int h[N], e[M], ne[M], w[M], ind;
    20. int deg[N], d[N], f[N], v[N];
    21. void add(int a, int b, int c) {
    22. e[ind] = b, w[ind] = c, ne[ind] = h[a], h[a] = ind++;
    23. }
    24. void dp(int x) {
    25. v[x] = 1;
    26. d[x] = 0;
    27. for (int i = h[x]; i; i = ne[i]) {
    28. int y = e[i];
    29. if (v[y])continue;
    30. dp(y);
    31. if (deg[y] == 1)d[x] += w[i];
    32. else d[x] += min(d[y], w[i]);
    33. }
    34. }
    35. void dfs(int x) {
    36. v[x] = 1;
    37. for (int i = h[x]; i; i = ne[i]) {
    38. int y = e[i];
    39. if (v[y])continue;
    40. if (deg[x] == 1)f[y] = d[y] + w[i];
    41. else if (deg[y] == 1)
    42. f[y] = d[y] + min(f[x] - w[i], w[i]);
    43. else
    44. f[y] = d[y] + min(f[x] - min(d[y], w[i]), w[i]);
    45. dfs(y);
    46. }
    47. }
    48. int main() {
    49. int T;
    50. scanf("%d", &T);
    51. while (T--) {
    52. scanf("%d", &n);
    53. memset(h, 0, sizeof(h));
    54. ind = 1;
    55. memset(deg, 0, sizeof(deg));
    56. for (int i = 1; i < n; i++) {
    57. int a, b, c;
    58. scanf("%d%d%d", &a, &b, &c);
    59. add(a, b, c), add(b, a, c);
    60. deg[a]++, deg[b]++;
    61. }
    62. int root = 1;
    63. memset(v, 0, sizeof v);
    64. dp(root);
    65. memset(v, 0, sizeof v);
    66. f[root] = d[root];
    67. dfs(root);
    68. int ans = 0;
    69. for (int i = 1; i <= n; i++)ans = max(ans, f[i]);
    70. cout << ans << endl;
    71. }
    72. return 0;
    73. }

  • 相关阅读:
    Java:实现测试一个数是否为素数算法(附完整源码)
    Docker部署FastDFS分布式存储
    Javascript 笔记:object
    linux下把文件夹压缩成tar.gz的命令
    LeetCode--155. 最小栈(C++描述)
    Vue响应式原理
    Linux - 性能可观察性工具
    Java 8被抛弃,甲骨文份额萎缩超一半,2022年Java生态报告出炉
    javaEE飞机航班信息查询网站系统
    C风格数组和std::array有什么区别
  • 原文地址:https://blog.csdn.net/Landing_on_Mars/article/details/133553680