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
 
题意:
给出一棵树,每个点当经过它时有一个获益,每个点的获益只能计算一次,每条边当经过它都有一个花费,需要重复计算。
询问从每个点出发,随意走的最大收益。
题解:
树形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值小,这点可以从定义或者方程看出。
 const int N = ;
int head[N], son[N * ], val[N * ], nex[N * ], tot;
int w[N], n;
struct FirstAndSecondMax {
pair<int, int> first, second; inline void init(int val, int id) {
first = second = make_pair(val, id);
} inline void addAll(int w) {
first.first += w, second.first += w;
} inline void updata(int val, int id) {
pair<int, int> now = make_pair(val, id);
if(first < now) swap(first, now);
if(second < now) swap(second, now);
} inline int getMax(int except) {
return first.second == except ? second.first : first.first;
}
} f[N];
int g[N];
// f -> maximum of paths that need not go back
// g -> maximum of paths that need to go back
#define cg(origin, cost) (max(0, origin - 2 * cost))
#define cf(origin, cost) (max(0, origin - cost))
// cg -> contribution to g
// cf -> contribution to f
int ans[N]; inline void init() {
for(int i = ; i < n; ++i) f[i].init(w[i], i);
for(int i = ; i < n; ++i) head[i] = -;
tot = ;
} inline void addEdge(int u, int v, int w) {
son[tot] = v, val[tot] = w, nex[tot] = head[u];
head[u] = tot++;
} int que[N], fa[N], valfa[N];
inline void bfs(int st) {
int len = ;
fa[st] = -, valfa[st] = INF, que[len++] = st;
for(int idx = ; idx < len; ++idx) {
int u = que[idx];
for(int tab = head[u], v; tab != -; tab = nex[tab])
if((v = son[tab]) != fa[u])
fa[v] = u, valfa[v] = val[tab], que[len++] = v;
}
} inline void solve() {
bfs(); for(int idx = n - ; idx >= ; --idx) {
int u = que[idx];
g[u] = w[u];
for(int tab = head[u], v; tab != -; tab = nex[tab])
if((v = son[tab]) != fa[u])
g[u] += cg(g[v], val[tab]);
f[u].init(g[u], u);
for(int tab = head[u], v; tab != -; tab = nex[tab])
if((v = son[tab]) != fa[u])
f[u].updata(g[u] - cg(g[v], val[tab]) +
f[v].getMax(u) - val[tab], v);
} for(int idx = ; idx < n; ++idx) {
int u = que[idx];
if(fa[u] != -) {
int faContributeIt = g[fa[u]] - cg(g[u], valfa[u]);
int lastg = g[u];
g[u] += cg(faContributeIt, valfa[u]);
f[u].addAll(cg(faContributeIt, valfa[u]));
f[u].updata(f[fa[u]].getMax(u) - cg(lastg, valfa[u])
- valfa[u] + lastg, fa[u]);
}
ans[u] = f[u].getMax(-);
} for(int i = ; i < n; ++i) printf("%d\n", ans[i]);
} int main() {
int testCase;
scanf("%d", &testCase);
for(int testIndex = ; testIndex <= testCase; ++testIndex) {
printf("Case #%d:\n", testIndex);
scanf("%d", &n);
for(int i = ; i < n; ++i) scanf("%d", &w[i]);
init();
for(int i = , u, v, w; i < n; ++i) {
scanf("%d%d%d", &u, &v, &w);
--u, --v;
addEdge(u, v, w), addEdge(v, u, w);
}
solve();
}
return ;
}

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

  1. 2016中国大学生程序设计竞赛 - 网络选拔赛 J. Alice and Bob

    Alice and Bob Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

  2. 2016中国大学生程序设计竞赛 网络选拔赛 I This world need more Zhu

    This world need more Zhu Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

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

    Problem Description Chisa Yukizome works as a teacher in the school. She prepares many gifts, which ...

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

    Problem Description Lweb has a string S. Oneday, he decided to transform this string to a new sequen ...

  5. 2016中国大学生程序设计竞赛 - 网络选拔赛 1001 A water problem (大数取余)

    Problem Descripton Two planets named Haha and Xixi in the universe and they were created with the un ...

  6. 2018中国大学生程序设计竞赛 - 网络选拔赛 1001 - Buy and Resell 【优先队列维护最小堆+贪心】

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6438 Buy and Resell Time Limit: 2000/1000 MS (Java/O ...

  7. 2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ's Salesman 【离散化+树状数组维护区间最大值】

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/O ...

  8. 2018中国大学生程序设计竞赛 - 网络选拔赛 1009 - Tree and Permutation 【dfs+树上两点距离和】

    Tree and Permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  9. HDU 6154 - CaoHaha's staff | 2017 中国大学生程序设计竞赛 - 网络选拔赛

    /* HDU 6154 - CaoHaha's staff [ 构造,贪心 ] | 2017 中国大学生程序设计竞赛 - 网络选拔赛 题意: 整点图,每条线只能连每个方格的边或者对角线 问面积大于n的 ...

随机推荐

  1. Git入门

    转: http://www.cnblogs.com/luxiaojun/p/5944145.html

  2. Holt-Winters原理和初始值的确定

      关于模型 (来自以下PPT,从第4页开始)   关于初始值: 以下文档给出了三个模型的初始值计算的思路. 大致思路如下,建立一个p阶移动平均模型,估计出参数即为初始值,具体的根据三种不同的模型,有 ...

  3. UVA-11997 K Smallest Sums

    UVA - 11997 K Smallest Sums Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & ...

  4. C# 操作office知识点汇总

    1. C#操作Word的超详细总结

  5. java基础 作业(一)

    题目: 跳水比赛,8个评委打分.运动员的成绩是8个成绩去掉一个最高分,去掉一个最低分,剩下的6个分数 的平均分就是最后 得分.使用以为数组实现打分功能 .请把打分最高的评委和最低的评委找出来. 解析: ...

  6. 周末娱乐一下--------恶搞windows小脚本

    下面这是个循环DOS命令,使用了C中的goto语句 echo命令式输出命令 set命令是设置命令 var是变量,初始为0 :continue是一个用于goto的标示. %var%输出变量名,%var% ...

  7. ngCloak 实现 Angular 初始化闪烁最佳实践

    在做angular的SPA开发时,我们经常会遇见在如Chrome这类能够快速解析的浏览器上出现表达式({{ express }} ),或者是模块(div)的闪烁.对于这个问题由于JavaScript去 ...

  8. nginx实现请求转发

    反向代理适用于很多场合,负载均衡是最普遍的用法. nginx 作为目前最流行的web服务器之一,可以很方便地实现反向代理. nginx 反向代理官方文档: NGINX REVERSE PROXY 当在 ...

  9. codeigniter钩子的使用

    CodeIgniter 的钩子功能,使得我们可以在不修改系统核心文件的基础上,来改变或增加系统的核心运行功能.可是钩子究竟该怎么用呢?虽然不是很难,不过很多刚用ci的朋友可能还是不明白怎么用. 通过本 ...

  10. PHP PHPUnit的简单使用

    1.window安装pear的教程:http://jingyan.baidu.com/article/ca41422fd8cf3d1eae99ed3e.html 2.在工作目录下,放两个文件: 1)C ...