51NOD算法马拉松21(迎新年) A - 1737 配对(dfs树的重心)
来源:互联网 发布:linux运维是必死之路 编辑:程序博客网 时间:2024/06/05 16:22
记录一个菜逼的成长。。
题目链接
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示例
6
1 2 1
1 3 1
1 4 1
3 5 1
4 6 1
Output示例
7
//配对方案为(1,2)(3,4)(5,6)
官方题解:
考虑每一条边被统计进答案几次。
若断开这条边后树形成大小为s1、s2的两个联通块则这条边最多被统计min(s1,s2)次。
构造方案的做法为:找出树的重心,让所有n/2条路径都经过重心即可(只要保证删去重心后任意同一联通块中的两点不构成路径即可,因为是重心,所以这是很好构造的)
这样构造出来的配对方案满足了每条边都没被统计min(s1,s2)次,所以这道题只要求出断开每条边后两个联通块的大小即可。
时间复杂度O(n)
简单的说,就是先求出树的重心,其余点到重心的带权路径长度和就是答案。
两次dfs。
一次求重心,一次求带权路径长度和。
这里有几个数组:
son[i] := 表示以i为根的子树的节点数,不包括自身。
dd[i] := 表示i到重心的带权路径长度。
#include <cstdio>#include <iostream>#include <algorithm>#include <vector>#include <cstring>#include <cmath>using namespace std;#define cl(a,b) memset(a,b,sizeof(a))#define pb push_back#define mp make_pair#define lowbit(x) (x)&(-x)typedef long long LL;typedef pair<int,int> PII;const int INF = 0x3f3f3f3f;const int MOD = 1e9 + 7;const int maxn = 100000 + 10;int son[maxn],vis[maxn];LL dd[maxn];int zx,Size;vector<PII>edge[maxn];int n;void init(){ for( int i = 1; i <= n; i++ )edge[i].clear(); cl(vis,0); cl(dd,0); Size = INF; zx = -1;}//求树的重心模板void dfs(int r){ vis[r] = 1; son[r] = 0; int tmp = 0; for( int i = 0; i < edge[r].size(); i++ ){ int v = edge[r][i].second; if(!vis[v]){ dfs(v); son[r] += son[v] + 1; tmp = max(tmp,son[v] + 1); } } tmp = max(tmp,n - son[r] - 1); if(tmp < Size){ zx = r; Size = tmp; }}void dfs1(int x){ vis[x] = 1; for( int i = 0; i < edge[x].size(); i++ ){ int v = edge[x][i].second; if(!vis[v]){ dd[v] = dd[x] + edge[x][i].first; dfs1(v); } }}int main(){ while(~scanf("%d",&n)){ init(); for( int i = 0; i < n - 1; i++ ){ int u,v,w; scanf("%d%d%d",&u,&v,&w); edge[u].pb(mp(w,v)); edge[v].pb(mp(w,u)); } dfs(1); cl(vis,0); dfs1(zx); LL ans = 0; for( int i = 1; i <= n; i++ ){ ans += dd[i]; } printf("%lld\n",ans); } return 0;}
0 0
- 51NOD算法马拉松21(迎新年) A - 1737 配对(dfs树的重心)
- 51nod 1737 配对【树的重心】
- 51nod 1737 配对 树的重心
- 51nod 1737 配对(树的重心)
- 51nod 1737 配对 && Codeforces 700B Connecting Universities【树的重心】
- 【51nod 算法马拉松19 A】区间的价值 V2
- 51nod 算法马拉松19 A P1674
- 51nod 1737【树的重心】
- 51nod算法马拉松21总结
- [FWT] 51Nod 算法马拉松26 A A国的贸易
- [FWT] 51nod 算法马拉松26 A. A国的贸易
- 51nod 算法马拉松3 A:序列分解
- 51nod 算法马拉松11 A 翻硬币
- 【51Nod算法马拉松18 A】染色问题
- [状态压缩||折半搜索]51nod 算法马拉松3 A
- [暴力 乱搞] 51Nod 1674 算法马拉松19 A 区间的价值 V2
- 51nod 算法马拉松12
- 51nod算法马拉松20
- iOS自定义UIDatepicker日期选择器视图
- Java单例的几种写法和优缺点
- Centos 7 系统安装完毕修改网卡名为eth0并设置静态IP
- 判断客户端是手机端还是PC端
- 第二周博客作业
- 51NOD算法马拉松21(迎新年) A - 1737 配对(dfs树的重心)
- 《C++ Primer Plus(第六版)》(38)(第十七章 输入、输出和文件 笔记1)
- JVM之 - Java内存模型
- 从入门到深入Fiddler (二)
- HTTP协议中PUT和POST使用区别
- Oralce如何修改间隔分区
- iOS常用控件介绍
- android高级知识汇总
- 自定义登陆人信息