您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树归