51nod 配对(求树的重心)
Posted 酱油党gsh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 配对(求树的重心)相关的知识,希望对你有一定的参考价值。
传送门:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737
给出一棵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)
这题一开始完全没思路,后来在评论中看到有人说是求树的重心再到其他点的距离和,就去查了下树的重心的定义——找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心。对于这题,配对的两点的路径一定要经过重心,这样才能保证距离最大,而如果任意两点都经过重心,他们的总距离一定是重心到其他点的距离和。这个模拟一下就能知道了。通过这题顺带学习一下树的重心。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <string> #include <stack> #include <map> #include <set> #include <bitset> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); #define in() freopen("data","r",stdin); #define out() freopen("ans","w",stdout); #define Clear(Q); while (!Q.empty()) Q.pop(); #define pb push_back using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 1e5 + 10; const int INF = 0x3f3f3f3f; struct Edge { int v, to; ll w; } E[2*maxn]; int head[maxn], cnt, n, sz, pos; int vis[maxn], sum[maxn]; ll dis[maxn]; ll ans = 0; void init() { sz = INF; clr(head, -1); clr(sum, 0); clr(dis, 0); cnt = 0; ans = 0; } void addedge(int v, int u, ll w) { E[cnt].v = u, E[cnt].w = w, E[cnt].to = head[v]; head[v] = cnt++; } void dfs(int cur)//求树的重心 { vis[cur] = 1; int temp = 0; for (int i = head[cur]; ~i; i = E[i].to) { int v = E[i].v; if (vis[v]) continue; dfs(v); temp = max(temp, sum[v] + 1);//求最大子树节点数 sum[cur] += sum[v] + 1; } temp = max(temp, n - sum[cur] - 1);//无向树还要考虑上半部分 if (temp < sz) { sz = temp; pos = cur; } } void solve(int cur)//算距离 { vis[cur] = 1; for (int i = head[cur]; ~i; i = E[i].to) { int v = E[i].v; if (vis[v]) continue; dis[v] = dis[cur] + E[i].w; ans += dis[v]; solve(v); } } int main() { init(); int v, u; ll w; scanf("%d", &n); for (int i = 1; i < n; i++) { scanf("%d%d%I64d", &v, &u, &w); addedge(v, u, w), addedge(u, v, w); } dfs(1); clr(vis, 0); //cout << sz << " " << pos << endl; solve(pos); cout << ans << endl; return 0; }
以上是关于51nod 配对(求树的重心)的主要内容,如果未能解决你的问题,请参考以下文章