51Nod-1424-零树
2017-06-24 01:36
190 查看
ACM模版
这个题十分有趣,如果树归基本功可以的话,题解应该是秒出的,而我就是差了那么点……还有注意
描述
题解
这个题是一个比较简单的树归了,从叶子开始向上求出来不同结点所需要的加减次数,最后输出 add[1]+sub[1] 即可,这里需要注意的是,一定要分开求加减次数,最开始我用 dfs 返回了一个 pair 表示某结点操作次数和偏移量,但是最后结果大了许多,仔细斟酌后发现,不同子树的加减操作如果混合在一起求那么会有很多重复的存在,必须将其分开来求,酱紫的话就不会存在子树之间的加减操作的重复现象了。这个题十分有趣,如果树归基本功可以的话,题解应该是秒出的,而我就是差了那么点……还有注意
long long,最开始因为这个还 WA 了一回,粗心大意害死人啊!
代码
#include <iostream> #include <cstdio> #include <vector> #include <cmath> using namespace std; typedef long long ll; const int MAXN = 1e5 + 10; int n; int val[MAXN]; ll add[MAXN]; ll sub[MAXN]; vector<int> vi[MAXN]; template <class T> inline bool scan_d(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) { return 0; //EOF } while (c != '-' && (c < '0' || c > '9')) { c = getchar(); } sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0' && c <= '9') { ret = ret * 10 + (c - '0'); } ret *= sgn; return 1; } void dfs(int root, int pre) { for (int i = 0; i < vi[root].size(); i++) { int tmp = vi[root][i]; if (tmp != pre) { dfs(tmp, root); add[root] = max(add[root], add[tmp]); sub[root] = max(sub[root], sub[tmp]); } } val[root] += add[root] - sub[root]; val[root] < 0 ? add[root] -= val[root] : sub[root] += val[root]; } int main(int argc, const char * argv[]) { // freopen("/Users/zyj/Desktop/input.txt", "r", stdin); scan_d(n); int a, b; for (int i = 1; i < n; i++) { scan_d(a), scan_d(b); vi[a].push_back(b); vi[b].push_back(a); } for (int i = 1; i <= n; i++) { scan_d(val[i]); } dfs(1, 0); cout << add[1] + sub[1] << '\n'; return 0; }
相关文章推荐
- 51nod 1424:零树
- 51nod 1424 零树
- 51nod-1424 零树
- 51nod 1424 零树(树dp)
- 51nod 1424 零树(树形dp)
- 51nod 1424 零树(树DP)
- 51nod-【1289 大鱼吃小鱼】
- 51nod 1495 中国好区间【2-pointers】
- 51nod 1011 【完全背包】
- 51nod 1407 与与与与 dp+容斥原理
- [数学] 51Nod 1622 算法马拉松19 C 集合对
- 【贪心+优先队列】51Nod 1053 最大M子段和 V2
- 51NOD 1674 区间的价值 V2
- 51nod 1503 猪和回文【DP】
- 51nod-1279 扔盘子
- 51nod 1678 lyk与gcd | 容斥原理
- 51nod 1004 n^n的末位数字
- 【51NOD 1551】集合交易
- 51nod 1024 矩阵中不重复的元素
- 51nod 1791 合法括号子段 (队列)