Shortest Path
题目链接:Shortest Path
Description
给定一颗个节点的树,保证为偶数。你需要将这个节点分成个点对,并最小化这个点对的距离之和。
多组数据。
数据范围
Solution
这其实是一道CF原题,原题既需要最小化值,也需要最大化值。
下面来谈谈最小化值。
既然是想要最小化,那么我们希望每一条边被访问的次数越少越好。
如果有一条以为父亲,为儿子的边,它的权值为,我们想尽可能少次数得经过它。
我们先跑一次,记录每一个节点的子树大小,如果为奇数,说明我在这个子树内无论如何匹配,总有一个点会被孤立的,那么这个点一定要经过到的这条边,所以这条边的贡献是;否则我一定可以不经过这条边。
所以,结论很明显了:如果,那么我肯定要计算到的权值作为贡献。
时间复杂度:。
Code
// Author: wlzhouzhuan #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define rint register int #define rep(i, l, r) for (rint i = l; i <= r; i++) #define per(i, l, r) for (rint i = l; i >= r; i--) #define mset(s, _) memset(s, _, sizeof(s)) #define pb push_back #define pii pair <int, int> #define mp(a, b) make_pair(a, b) #define Each(i) for (rint i = head[u]; i; i = edge[i].nxt) inline int read() { int x = 0, neg = 1; char op = getchar(); while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); } while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); } return neg * x; } inline void print(int x) { if (x < 0) { putchar('-'); x = -x; } if (x >= 10) print(x / 10); putchar(x % 10 + '0'); } const int N = 10005; struct Edge { int to, nxt, val; } edge[N << 1]; int head[N], tot; void add(int u, int v, int w) { edge[++tot] = {v, head[u], w}; head[u] = tot; } int n; long long ans = 0; int sz[N]; void dfs(int u, int fa) { sz[u] = 1; Each(i) { int v = edge[i].to; if (v == fa) continue; dfs(v, u); sz[u] += sz[v]; if (sz[v] & 1) { // 这个子树的大小为奇数 ans += edge[i].val; } } } int main() { int T = read(); while (T--) { n = read(); for (int i = 1; i <= n; i++) { head[i] = 0; } tot = ans = 0; for (int i = 1; i < n; i++) { int u = read(), v = read(), w = read(); add(u, v, w); add(v, u, w); } dfs(1, 0); printf("%lld\n", ans); } return 0; }