码迷,mamicode.com
首页 > 其他好文 > 详细

CF 686D. Kay and Snowflake

时间:2019-11-10 17:24:24      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:++   +=   highlight   amp   dfs   for   names   有一个   pac   

给你一个树N个点,再给出Q个询问,问以x为根的子树中,重心是哪个?
2≤n≤300000,1≤q≤30000

Sol:
从下到上,根据性质做一下.
1:如果某个点x,其子树y的大小超过总结点个数一半,则重心在y这个子树中。
2:如果某个树的重心点,其上方点的个数多于其下方点的,则重心要上移

#include <bits/stdc++.h>
using namespace std;
const int N = 300000+10;
int n,q;
vector<int> G[N]; ///存图
int ans[N];       ///答案
int son[N];       ///包括自身在内有多少子树结点
int fa[N];        ///输入用,同时代表这个点的父亲
 
void dfs(int u){
    ans[u] = u;//当只有一个点时,重心为其自己 
    son[u] = 1;
    for(int i = 0;i < G[u].size();i++){
        int v = G[u][i];
        dfs(v);
        son[u] += son[v];
    }
    for(int i = 0;i < G[u].size();i++)     
        if(son[G[u][i]]*2 > son[u])
		//如果有一个子树超过总个数一半,则重心在这个子树中        
		    ans[u] = ans[G[u][i]];
    while((son[u]-son[ans[u]])*2 > son[u]) 
    //如果当前重心上方的点,比它下方的点要多,则重心要进行移动 
        ans[u] = fa[ans[u]];
}
 
int main(void)
{
    scanf("%d%d",&n,&q);
    for(int i = 2;i <= n;i++){
        scanf("%d",&fa[i]);
        G[fa[i]].push_back(i);
    }
    dfs(1);
    for(int i = 1;i <= q;i++){
        int qq;
        scanf("%d",&qq);
        printf("%d\n",ans[qq]);
    }
    return 0;
}

  

CF 686D. Kay and Snowflake

标签:++   +=   highlight   amp   dfs   for   names   有一个   pac   

原文地址:https://www.cnblogs.com/cutemush/p/11830897.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!