1737 配对

来源:互联网 发布:sql identity是什么 编辑:程序博客网 时间:2024/05/16 06:40
1737 配对

 

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
 收藏
 关注
给出一棵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示例
61 2 11 3 11 4 13 5 14 6 1
Output示例
7//配对方案为(1,2)(3,4)(5,6)
﹡    LH (题目提供者)
 
 
考虑每一条边被统计进答案几次。
若断开这条边后树形成大小为s1、s2的两个联通块则这条边最多被统计min(s1,s2)次。
构造方案的做法为:找出树的重心,让所有n/2条路径都经过重心即可(只要保证删去重心后任意同一联通块中的两点不构成路径即可,因为是重心,所以这是很好构造的)
这样构造出来的配对方案满足了每条边都没被统计min(s1,s2)次,所以这道题只要求出断开每条边后两个联通块的大小即可。
时间复杂度O(n)
 
 1 #include <cstdio> 2 #include <cctype> 3 #include <vector> 4  5 typedef long long LL; 6 const int MAXN=100010; 7  8 int n; 9 10 LL ans;11 12 int son[MAXN];13 14 struct node {15     int to,val;16     node() {}17     node(int to,int val):to(to),val(val) {}18 };19 20 std::vector<node> Graph[MAXN];21 22 inline void read(int&x) {23     int f=1;register char c=getchar();24     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());25     for(;isdigit(c);x=x*10+c-48,c=getchar());26     x=x*f;27 }28 29 void DFS(int now,int fa) {30     son[now]=1;31     for(register int i=0;i<Graph[now].size();++i) {32         node p=Graph[now][i];33         if(p.to==fa) continue;34         DFS(p.to,now);35         son[now]+=son[p.to];36     }37     return;38 }39 40 void DFS_Ans(int now,int fa) {41     for(register int i=0;i<Graph[now].size();++i) {42         node p=Graph[now][i];43         if(p.to==fa) continue;44         DFS_Ans(p.to,now);45         ans+=(LL)(son[p.to]<n-son[p.to]?son[p.to]:(n-son[p.to]))*p.val;46     }47     return;48 }49 50 int hh() {51     read(n);52     for(register int x,y,z,i=1;i<n;++i) {53         read(x);read(y);read(z);54         Graph[y].push_back(node(x,z));55         Graph[x].push_back(node(y,z));56     }57     DFS(1,0);58     DFS_Ans(1,0);59     printf("%lld\n",ans);60     return 0;61 }62 63 int sb=hh();64 int main(int argc,char**argv) {;}
代码

 

原创粉丝点击