D. Kay and Snowflake 树的重心
http://codeforces.com/contest/686/problem/D
给出q个询问,每次要求询问以x为根的子树中,哪一个点是重心。
树的重心:求以cur为根的子树的重心,就是要找一个点,使得删除这个点后,分开来的零散的子树中,节点数的最大值最小。并且最大值最多也只是son[cur] / 2,因为最坏情况(最难分)也就是一条直线,选中间点就可以了。
例如

询问1的时候,就应该删除3,然后得到4个零散分支,2个大小是1,2个是2。
算法思路:
直观来说,应该是删除那个儿子数最多的那个节点的。 比如上图,3的儿子数最多,所以询问1就删除3了。因为,没理由再分一些节点给最大的那颗子树把,这样只会更坏。
但是却可以把最大的那颗子树分一些节点去另一边,所以优先删除最大的那颗子树的重心,然后判断是否符合要求,不符合就只能暴力往上找了。
判定条件是son[cur] > 2 * son[重心]就不行。
因为这表明son[cur] - son[重心]的值还大于son[cur] / 2
代进去就知道了son[cur] - son[重心] > son[重心],
假设son[cur] = 2 * son[重心]。那么就是剩下的节点数会大于son[cur] / 2咯。。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = + ;
int ans[maxn];
int son[maxn]; //第u个点有多少个儿子。
int fa[maxn]; //记录第i个点的爸爸是谁
struct node {
int u, v, tonext;
}e[maxn];
int first[maxn]; int num;
void add(int u, int v) {
++num;
e[num].u = u;
e[num].v = v;
e[num].tonext = first[u];
first[u] = num;
}
void dfs(int cur, int from) {
son[cur] = ; //自己一个
ans[cur] = cur; //叶子节点
int mx = -inf, pos = cur; //以这个点为子树的儿子数最多的那个pos
for (int i = first[cur]; i; i = e[i].tonext) {
dfs(e[i].v, cur);
son[cur] += son[e[i].v]; //加上儿子的节点个数
if (mx < son[e[i].v]) { //不能算自己,只能算儿子的max
mx = son[e[i].v];
pos = e[i].v; //儿子数最多的那个节点,
}
}
ans[cur] = ans[pos]; //ans[pos]已经算出来了,ans[pos]的重心
while (son[cur] > * son[ans[cur]]) {
ans[cur] = fa[ans[cur]]; //暴力往上找
}
}
void work() {
int n;
cin >> n;
int q;
cin >> q;
for (int i = ; i <= n; ++i) {
int x;
cin >> x;
add(x, i);
fa[i] = x;
}
dfs(, -);
for (int i = ; i <= q; ++i) {
int x;
cin >> x;
cout << ans[x] << endl;
}
} int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
IOS;
work();
return ;
}
重心的定义是:
找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡
(一)
树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么他们的距离和一样。
(二)
把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上。
(三)
把一个树添加或删除一个叶子,那么它的重心最多只移动一条边的距离。
D. Kay and Snowflake 树的重心的更多相关文章
- Codeforces Round #359 (Div. 2) D. Kay and Snowflake 树的重心
题目链接: 题目 D. Kay and Snowflake time limit per test 3 seconds memory limit per test 256 megabytes inpu ...
- codeforces 685B Kay and Snowflake 树的重心
分析:就是找到以每个节点为根节点的树的重心 树的重心可以看这三篇文章: 1:http://wenku.baidu.com/link?url=yc-3QD55hbCaRYEGsF2fPpXYg-iO63 ...
- Codeforces Round #359 (Div. 2) D. Kay and Snowflake 树DP
D. Kay and Snowflake After the piece of a devilish mirror hit the Kay's eye, he is no longer int ...
- Kay and Snowflake CodeForces - 685B (重心, 好题)
大意:给定有根树, 求每个子树的重心 我太菜了啊, 只能想到暴力树剖, 然而这就是个B题, 感觉树剖+线段树二分还是挺难写的..... 看了题解发现重心一定在重儿子与根的树链上, 重心最多上跳n-1次 ...
- Kay and Snowflake CodeForces - 686D (树的重心性质)
After the piece of a devilish mirror hit the Kay's eye, he is no longer interested in the beauty of ...
- B. Kay and Snowflake 解析(思維、DFS、DP、重心)
Codeforce 685 B. Kay and Snowflake 解析(思維.DFS.DP.重心) 今天我們來看看CF685B 題目連結 題目 給你一棵樹,要求你求出每棵子樹的重心. 前言 完全不 ...
- CF685B Kay and Snowflake 贪心
CF685B Kay and Snowflake 链接 CF 题目大意 给你一颗树,询问子树的重心 思路 贪心? 重心肯定是向上走的,所以直接向上跳就好了. 不优秀的时候就不要跳了 ,因为以后也不能更 ...
- Codeforces Round #359 (Div. 2) D - Kay and Snowflake
D - Kay and Snowflake 题目大意:给你一棵数q个询问,每个询问给你一个顶点编号,要你求以这个点为根的子树的重心是哪个节点. 定义:一棵树的顶点数为n,将重心去掉了以后所有子树的顶点 ...
- Codeforces 686 D - Kay and Snowflake
D - Kay and Snowflake 思路: 树的重心 利用重心的一个推论,树的重心必定在子树重心的连线上. 然后利用重心的性质,可知,如果有一颗子树的大小超过整棵树的大小的1/2,那么树的重心 ...
随机推荐
- BluetoothLE-Multi-Library 一个能够连接多台蓝牙设备的库,它可以作为client端,也可以为server端。支持主机/从机,外围设备连接。
github地址:https://github.com/qindachang/BluetoothLE-Multi-Library BluetoothLE-Multi-Library 一个能够连接多台蓝 ...
- struts2 学习日记1
struts2 简介 struts2的前身可以说是framework.strut1作为当时很流行的框架,但是有很多的不足之处,framework出生后,它带来了很好的框架,但是很多人已经习惯了stru ...
- linguistic相关
Knowing a word means knowing both its sound and its meaning, while being able to use a word requires ...
- juery的跨域请求2
时间过得好快,又被拉回js战场时, 跨域问题这个伤疤又开疼了. 好在,有jquery帮忙,跨域问题似乎没那么难缠了.这次也借此机会对跨域问题来给刨根问底,结合实际的开发项目,查阅了相关资料,算是解决了 ...
- maven的常用构建命令
mvn clean:删除项目根目录中的target目录
- C++ 两款静态检查工具
pclint(收费) http://www.gimpel.com/html/pcl.htmpc-lint是资格最老,最强力的代码检查工具,但是是收费软件,并且配置起来有一点点麻烦. ccpchecke ...
- 【linux+C】神器 vim + 指针相关客串
前篇回顾 上篇介绍了linux下C编程基本环境配置以及相关工具使用选择. 不过10个大牛9个用vim,那么咱们就来玩vim.linux下玩c就别依靠图形界面.好吧告别Ide,命令行才是c的王道. 本篇 ...
- bzoj4066
KD-tree 强制在线就不能愉快的做这道题了. 我们用KD-tree维护平面上的点,这样建出来的树高大概是log,复杂度过得去,但是插入过多会使树深很深,这样就能卡死,那么我们每个10000次插入就 ...
- 使用 Git 命令去管理项目的版本控制(一)
参考资料:参考 参考 声明本文是作者原创,是自己的学习笔记,仅供学习参考. 在 10.11.2Mac系统中,要显示隐藏的文件夹使用命令行: defaults write com.apple.find ...
- Ubuntu 下编译Android 源代码
1.配置JDK 1.6 或者1.7(看情况配置,有的Android版本不能在1.7下运行) 2.配置环境:终端:(CTRL+ALT+T) $ sudo apt-get install git gnup ...