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 树的重心的更多相关文章

  1. 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 ...

  2. codeforces 685B Kay and Snowflake 树的重心

    分析:就是找到以每个节点为根节点的树的重心 树的重心可以看这三篇文章: 1:http://wenku.baidu.com/link?url=yc-3QD55hbCaRYEGsF2fPpXYg-iO63 ...

  3. 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 ...

  4. Kay and Snowflake CodeForces - 685B (重心, 好题)

    大意:给定有根树, 求每个子树的重心 我太菜了啊, 只能想到暴力树剖, 然而这就是个B题, 感觉树剖+线段树二分还是挺难写的..... 看了题解发现重心一定在重儿子与根的树链上, 重心最多上跳n-1次 ...

  5. 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 ...

  6. B. Kay and Snowflake 解析(思維、DFS、DP、重心)

    Codeforce 685 B. Kay and Snowflake 解析(思維.DFS.DP.重心) 今天我們來看看CF685B 題目連結 題目 給你一棵樹,要求你求出每棵子樹的重心. 前言 完全不 ...

  7. CF685B Kay and Snowflake 贪心

    CF685B Kay and Snowflake 链接 CF 题目大意 给你一颗树,询问子树的重心 思路 贪心? 重心肯定是向上走的,所以直接向上跳就好了. 不优秀的时候就不要跳了 ,因为以后也不能更 ...

  8. Codeforces Round #359 (Div. 2) D - Kay and Snowflake

    D - Kay and Snowflake 题目大意:给你一棵数q个询问,每个询问给你一个顶点编号,要你求以这个点为根的子树的重心是哪个节点. 定义:一棵树的顶点数为n,将重心去掉了以后所有子树的顶点 ...

  9. Codeforces 686 D - Kay and Snowflake

    D - Kay and Snowflake 思路: 树的重心 利用重心的一个推论,树的重心必定在子树重心的连线上. 然后利用重心的性质,可知,如果有一颗子树的大小超过整棵树的大小的1/2,那么树的重心 ...

随机推荐

  1. D3.JS V4 绘制中国地图

    参考:http://bl.ocks.org/almccon/fe445f1d6b177fd0946800a48aa59c71 http://blog.csdn.net/lzhlzz/article/d ...

  2. bootstrap 学习笔记(1)---介绍bootstrap和栅格系统

    学习前端许久,对于布置框架和响应浏览器用html 和javascript 写的有点繁琐,无意间看到这个框架,觉得挺好用的就开始学习了,但是这个框架上面有很多知识,不是所有的都要学的,故将学习笔记和觉得 ...

  3. DLL的远程注入技术

    DLL的远程注入技术是目前Win32病毒广泛使用的一种技术.使用这种技术的病毒体通常位于一个DLL中,在系统启动的时候,一个EXE程序会将这个DLL加载至某些系统进程(如Explorer.exe)中运 ...

  4. ORM学习 一 : JPA JDBC

    JDBC jdbc是一组规范,是接口,由不同的数据库厂商各自提供相应的实现类,打包成jar包,也就是所谓的数据库驱动.而我们的java应用程序,只需要调用jdbc的接口就可以了. 什么是JPA Jav ...

  5. Union All ,Merge,Merge join 区别

    本文转自:http://www.cnblogs.com/gudujianxiao/archive/2012/07/17/2594709.html SSIS Data Flow 中有几个组件可以实现不同 ...

  6. 使用IntelliJ IDEA配置Tomcat(入门)

    一.下载Tomcat 1.进入官网http://tomcat.apache.org/,选择download,下载所需Tomcat版本. 此处我们选择下载最新版本Tomcat 9. 注意有zip和exe ...

  7. android调试之adb

    ADB 其实大部分的PC开发机与Android设备的操作都是通过adb(android debug bridge)技术完成的,这是一个C/S架构的命令行工具,主要由三个部分组成 运行在PC开发机上的命 ...

  8. SparseArray浅析

    HashMap是java里比较常用的一个集合类,我们一般用来缓存一些处理后的结果.但当你做一个Android项目时,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performanc ...

  9. css 属性相关

    css属性相关 宽和高 width属性可以为元素设置宽度, height属性可以为元素设置好高度 块级标签才能设置宽度,内联标签的宽度由内容来决定. 字体属性 文字字体 font-family 可以把 ...

  10. C#实现简易ajax调用后台方法

    在当前WEB当中,有些人都会抛弃asp.net的服务器控件,转而使用ajax来进行数据的交互和存储. 当我们大量使用ajax的时候,对于新手而言,肯定会创建很多的ashx或aspx页面,通过拼接参数, ...