题意:给出一棵有偶数的节点的树,将其分成n/2对点,并且要求n/2对点的路径之和最小
思路:树上任意两点间的距离是唯一的,题目又要求路径之和最小,所以选择两个节点,要么是父节点和其孩子节点,要么是父节点的两个孩子节点,还有一种情况是多了一个孩子节点,那么肯定要先加上到父节点的距离,然后再和另外一个节点配对。
所以在树上dfs,枚举子树的节点个数,一颗子树如果节点个数为偶数,就不需要再添加节点配对,如果节点个数为奇数,需要和父节点往外的一个节点配对,那么答案就要加上这颗子树到父节点的距离
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; typedef long long ll; struct node { int t, w, next; } edge[maxn << 1]; int n, cnt; int head[maxn], tot[maxn]; ll ans; void add(int x, int y, int z) { edge[++cnt].t = y; edge[cnt].w = z; edge[cnt].next = head[x]; head[x] = cnt; } void dfs(int x, int fa, int len) { tot[x] = 1; for (int i = head[x]; ~i; i = edge[i].next) { int y = edge[i].t; if (y == fa) continue; dfs(y, x, edge[i].w); tot[x] += tot[y]; } if (tot[x] % 2 == 1) ans += len; } int main() { int t; scanf("%d", &t); while (t--) { ans = 0, cnt = 0; scanf("%d",&n); memset(head, -1, sizeof(head)); memset(tot, 0, sizeof(tot)); for (int i = 1; i <= n - 1; ++i) { int x, y, w; scanf("%d%d%d", &x, &y, &w); add(x, y, w); add(y, x, w); } dfs(1, 0, 0); printf("%lld\n", ans); } return 0; }