2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree

Magic boy Bi Luo with his excited tree

Problem Description

Bi Luo is a magic boy, he also has a migic tree, the tree has N nodes , in each node , there is a treasure, it‘s value is V[i], and for each edge, there is a cost C[i], which means every time you pass the edge i , you need to pay C[i].

You may attention that every V[i] can be taken only once, but for some C[i] , you may cost severial times.

Now, Bi Luo define ans[i] as the most value can Bi Luo gets if Bi Luo starts at node i.

Bi Luo is also an excited boy, now he wants to know every ans[i], can you help him?

Input

First line is a positive integer T(T≤104) , represents there are T test cases.

Four each test:

The first line contain an integer N(N≤105).

The next line contains N integers V[i], which means the treasure’s value of node i(1≤V[i]≤104).

For the next N−1 lines, each contains three integers u,v,c , which means node u and node v are connected by an edge, it‘s cost is c(1≤c≤104).

You can assume that the sum of N will not exceed 106.

Output

For the i-th test case , first output Case #i: in a single line , then output N lines , for the i-th line , output ans[i] in a single line.

Sample Input

1
5
4 1 7 7 7
1 2 6
1 3 1
2 4 8
3 5 2

Sample Output

Case #1:
15
10
14
9
15

Author

UESTC

Source

2016中国大学生程序设计竞赛 - 网络选拔赛

题意:
    给出一棵树,每个点当经过它时有一个获益,每个点的获益只能计算一次,每条边当经过它都有一个花费,需要重复计算。
    询问从每个点出发,随意走的最大收益。
题解:
    树形dp。
    比赛时没有A掉。。。队友没有采取我的思路写,按照他们推的公式写了。。。
    (其实是当时我在写其他题,我写完他们直接上了。。。实际上不用那么急,
    (当时比赛结束还有1.5h,好好整理思路写说不定就过了
    其实我觉得我的思路是比较简单明了的。。
    今天写了一下,从整理题目思路在内到AC,只花了1h,一发就AC了。。。

    设f[i]代表每个点出去随便走不一定回来的最大收益和次大收益(一对数),
    个g[i]代表每个点出去随便走一定要回来的最大收益。

    按照bfs序扫两遍。
    第一遍,按照bfs序倒着扫:
        统计每个点只能往下走的 f 和 g。
        这部分是非常简单的dp,方程
        g[i] = sigma(max(0, g[child] - 2 * costOfEdge))
        f[i] = max(g[i],
                            g[i] - max(0, g[child] - 2 * costOfEdge) + f[child] + costOfEdge)
        计算f时先将孩子对g[i]的贡献减去加上本次贡献就行了。

    第二遍,按照bfs序正着扫:
        统计每个点的f和g,加入父亲的影响。
        也就是说此时的f和g的意义变为不仅仅可以往下走还可以往父亲边走,就是随便走。
        统计时类似,先减去自己对父亲的影响,再利用父亲的f和g更新自己。
        转移方程这里写的不方便,具体可以查看代码。

    最后每个点的f值就是答案。
    因为f值不会比g值小,这点可以从定义或者方程看出。

  1 const int N = 100010;
  2 int head[N], son[N * 2], val[N * 2], nex[N * 2], tot;
  3 int w[N], n;
  4 struct FirstAndSecondMax {
  5     pair<int, int> first, second;
  6
  7     inline void init(int val, int id) {
  8         first = second = make_pair(val, id);
  9     }
 10
 11     inline void addAll(int w) {
 12         first.first += w, second.first += w;
 13     }
 14
 15     inline void updata(int val, int id) {
 16         pair<int, int> now = make_pair(val, id);
 17         if(first < now) swap(first, now);
 18         if(second < now) swap(second, now);
 19     }
 20
 21     inline int getMax(int except) {
 22         return first.second == except ? second.first : first.first;
 23     }
 24 } f[N];
 25 int g[N];
 26 // f -> maximum of paths that need not go back
 27 // g -> maximum of paths that need to go back
 28 #define cg(origin, cost) (max(0, origin - 2 * cost))
 29 #define cf(origin, cost) (max(0, origin - cost))
 30 // cg -> contribution to g
 31 // cf -> contribution to f
 32 int ans[N];
 33
 34 inline void init() {
 35     for(int i = 0; i < n; ++i) f[i].init(w[i], i);
 36     for(int i = 0; i < n; ++i) head[i] = -1;
 37     tot = 0;
 38 }
 39
 40 inline void addEdge(int u, int v, int w) {
 41     son[tot] = v, val[tot] = w, nex[tot] = head[u];
 42     head[u] = tot++;
 43 }
 44
 45 int que[N], fa[N], valfa[N];
 46 inline void bfs(int st) {
 47     int len = 0;
 48     fa[st] = -1, valfa[st] = INF, que[len++] = st;
 49     for(int idx = 0; idx < len; ++idx) {
 50         int u = que[idx];
 51         for(int tab = head[u], v; tab != -1; tab = nex[tab])
 52             if((v = son[tab]) != fa[u])
 53                 fa[v] = u, valfa[v] = val[tab], que[len++] = v;
 54     }
 55 }
 56
 57 inline void solve() {
 58     bfs(1);
 59
 60     for(int idx = n - 1; idx >= 0; --idx) {
 61         int u = que[idx];
 62         g[u] = w[u];
 63         for(int tab = head[u], v; tab != -1; tab = nex[tab])
 64             if((v = son[tab]) != fa[u])
 65                 g[u] += cg(g[v], val[tab]);
 66         f[u].init(g[u], u);
 67         for(int tab = head[u], v; tab != -1; tab = nex[tab])
 68             if((v = son[tab]) != fa[u])
 69                 f[u].updata(g[u] - cg(g[v], val[tab]) +
 70                         f[v].getMax(u) - val[tab], v);
 71     }
 72
 73     for(int idx = 0; idx < n; ++idx) {
 74         int u = que[idx];
 75         if(fa[u] != -1) {
 76             int faContributeIt = g[fa[u]] - cg(g[u], valfa[u]);
 77             int lastg = g[u];
 78             g[u] += cg(faContributeIt, valfa[u]);
 79             f[u].addAll(cg(faContributeIt, valfa[u]));
 80             f[u].updata(f[fa[u]].getMax(u) - cg(lastg, valfa[u])
 81                        - valfa[u] + lastg, fa[u]);
 82         }
 83         ans[u] = f[u].getMax(-1);
 84     }
 85
 86     for(int i = 0; i < n; ++i) printf("%d\n", ans[i]);
 87 }
 88
 89 int main() {
 90     int testCase;
 91     scanf("%d", &testCase);
 92     for(int testIndex = 1; testIndex <= testCase; ++testIndex) {
 93         printf("Case #%d:\n", testIndex);
 94         scanf("%d", &n);
 95         for(int i = 0; i < n; ++i) scanf("%d", &w[i]);
 96         init();
 97         for(int i = 1, u, v, w; i < n; ++i) {
 98             scanf("%d%d%d", &u, &v, &w);
 99             --u, --v;
100             addEdge(u, v, w), addEdge(v, u, w);
101         }
102         solve();
103     }
104     return 0;
105 }

时间: 2024-12-25 23:01:09

2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree的相关文章

2016中国大学生程序设计竞赛 - 网络选拔赛

solved 4/11 2016中国大学生程序设计竞赛 - 网络选拔赛

HDU 5833 Zhu and 772002(高斯消元)——2016中国大学生程序设计竞赛 - 网络选拔赛

传送门 Zhu and 772002 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 48    Accepted Submission(s): 16 Problem Description Zhu and 772002 are both good at math. One day, Zhu wants to test the abili

HDU 5832 A water problem(取模~)—— 2016中国大学生程序设计竞赛 - 网络选拔赛

传送门 A water problem Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 60    Accepted Submission(s): 37 Problem Description Two planets named Haha and Xixi in the universe and they were created wit

2016中国大学生程序设计竞赛 - 网络选拔赛 1004 Danganronpa

Problem Description Chisa Yukizome works as a teacher in the school. She prepares many gifts, which consist of n kinds with a[i] quantities of each kind, for her students and wants to hold a class meeting. Because of the busy work, she gives her gift

2016中国大学生程序设计竞赛 - 网络选拔赛 1011 Lweb and String

题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1011&cid=719 Sample Input 2 aabcc acdeaa Sample Output Case #1: 3 Case #2: 4 *************************************************** 题意:我只能说题意神马都是浮云,纯属干扰,直接看代码吧 1 #include<stdio.h> 2 #i

【数论】2016中国大学生程序设计竞赛 - 网络选拔赛 A. A water problem (大整数取模)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5832 题意:两个星球,一个星球一年只有137天,一个星球一年只有73天 输入N(爆炸后第N天),判断这是否为这两个星球的第一天 只要这个数是137与73的公倍数就好了(0比较特殊) 坑点:N的长度不超过10000000 只能用字符串来存储 大整数整除:紫书P314 大整数整除:首先把大整数写成"自左向右"的形式:1234 = (((1*10)+2)*10+3)*10+4 然后每步取模 代码 1

【STL】【HDU5842】2016中国大学生程序设计竞赛 - 网络选拔赛 K. Lweb and String (set)(水~~~)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5842 水题,可以用来练习STL中的set 题目大意:给你一串字符串,字符串中的某个字母可以替换为一个数字,求最长上升子序列 例如: aabcdef --> 1123456 acdeaa  --> 123411    aabcc    --> 11233    dacbdda--> 1234112 红色字体为最长上升子序列 所以我们只需要统计有多少种不同的字母便可以得到答案 代码:(set解

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha&#39;s staff 思维

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6154 题意:在笛卡尔坐标系下,画一个面积至少为  n 的简单多边形,每次只能画一条边或者一个格子的对角线,问至少要画几条. 解法:如果一个斜着的矩形长宽分别是 a,b,那么它的面积是 2ab.最优解肯定是离 sqrt(n/2)很近的位置.想想 n=5 时答案为什么是7 然后在那个小范围内枚举一下就好了.我给一张做题时画的图 #include <bits/stdc++.h> using namesp

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha&#39;s staff(几何找规律)

Problem Description "You shall not pass!"After shouted out that,the Force Staff appered in CaoHaha's hand.As we all know,the Force Staff is a staff with infinity power.If you can use it skillful,it may help you to do whatever you want.But now,hi