51Nod - 1737 树形dp

来源:互联网 发布:python编码格式转换 编辑:程序博客网 时间:2024/05/19 02:00

题意:

给出一棵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示例
61 2 11 3 11 4 13 5 14 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;}


0 0
原创粉丝点击