您的位置:首页 > 其它

51Nod - 1737 树形dp

2017-01-23 14:51 316 查看

题意:

给出一棵n个点的树,将这n个点两两配对,求所有可行的方案中配对两点间的距离的总和最大为多少。

Input
一个数n(1<=n<=100,000,n保证为偶数)
接下来n-1行每行三个数x,y,z表示有一条长度为z的边连接x和y(0<=z<=1,000,000,000)


Output
一个数表示答案


Input示例
6
1 2 1
1 3 1
1 4 1
3 5 1
4 6 1


Output示例
7
//配对方案为(1,2)(3,4)(5,6)


思路:

树形dp,算贡献,单独考虑其中某一条边(u,v),因为是树上的边,所以一定是桥,假设u的一共有x个点,那么v这边一共就有n-x个点。如果要使得最后的结果最大,应该让每条边都尽可能多的被算。从贡献上来考虑,每条边的能被算次数的上限就是min(x,n-x),根据这个思路然后树形dp一波就行了。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;

struct node {
int v, w;
};

int n;
ll ans;
vector <node> tree[MAXN];

int dfs(int u, int pre) {
int cnt = tree[u].size(), res = 1;
for (int i = 0; i < cnt; i++) {
int v = tree[u][i].v, w = tree[u][i].w;
if (v == pre) continue;
int sonnum = dfs(v, u);
ans += (ll)min(sonnum, n - sonnum) * w;
res += sonnum;
}
return res;
}

int main() {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
tree[u].push_back((node) {v, w});
tree[v].push_back((node) {u, w});
}
ans = 0;
dfs(1, -1);
printf("%I64d\n", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm dp