题目大意
给你2n个结点组成的树,问n个点对(包含所有点)的最小距离和以及最大距离和。
解题思路
问题和边权的大小无关,只考虑用边的次数。
如果要使距离和最小那么就尽量的让一条边只用一次,对于一条边连接的两个连通块来说,如果两边都是奇数个点,就需要两个点通过这条边相连,所以就加上这条边,否则的话,就不需要这条边。
如果要使距离和最大,那么每条边用的次数就尽可能多,如果要使每个点都连上另一个点,那么这条边可以用的最大次数就是连接的两个连通块的点数的最小值。
代码
const int maxn = 2e5+10;
const int maxm = 2e3+10;
vector<P> e[maxn];
int n, d[maxn];
ll minn, maxx;
int dfs(int u, int w, int p) {
d[u] = 1;
for (auto v : e[u])
if (v.y!=p) d[u] += dfs(v.y, v.x, u);
if (d[u]&1) minn += w;
maxx += 1LL*min(n-d[u], d[u])*w;
return d[u];
}
int main() {
int __; cin >> __;
while(__--) {
cin >> n; n <<= 1;
for (int i = 1, a, b, c; i<n; ++i) {
scanf("%d%d%d", &a, &b, &c);
e[a].push_back({c, b});
e[b].push_back({c, a});
}
minn = maxx = 0;
dfs(1, 0, -1);
cout << minn << ' ' << maxx << endl;
for (int i = 1; i<=n; ++i) d[i] = 0, e[i].clear();
}
return 0;
}