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; }
相关文章推荐
- 51nod 1737 配对 【树形dp】
- [51nod] 1378 夹克老爷的愤怒 #树形DP
- 51nod 1314 定位系统 树形dp
- 51nod 1299 监狱逃离 树形dp/最小割
- 51nod 1405 树的距离之和 (两次dfs,树形dp)
- 51NOD-1405 树的距离之和(树形DP)
- 51nod 1378 夹克老爷的愤怒(树形dp,贪心)
- 51nod 1405 树的距离之和 【dfs--记忆dp??树形dp??】
- 51nod 1500 苹果曼和树【树形DP】
- 51nod 1500 苹果曼和树 树形DP
- 51nod 苹果曼和树 (树形dp)
- 51nod 1405 树的距离之和【树形dp】
- 51Nod 1405 树的距离之和(树形dp)
- 51nod 1405 树的距离之和 (两次dfs,树形dp)
- 51nod 1299 监狱逃离 树形dp
- 51Nod - 1677 树形dp + 组合数学
- 51nod 1378 夹克老爷的愤怒(树形dp)
- 51Nod-1412-AVL树的种类(树形dp)
- 【树形DP】51Nod 1500 苹果曼和树
- 51nod 1405 树的距离之和 (树形dp)