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

cf 686D - Kay and Snowflake

时间:2020-02-11 23:07:48      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:ems   ++   操作   from   using   efi   nod   src   spl   

题意让你求每个子树的重心

直接求肯定不行对吧......然后又是在树上

考虑树的重心的性质

1.任意一个子树小于当前树的二分之一     (换句话  一棵树的重心一定是自己或者是重儿子子树上)

2.当两个子树连接的时候新接成的树的重心一定在  两个子树重心的路径上

 

然后发现.....这个题  可以直接分治   跑  然后就没了

 

 

嘛....主要我不会写....(就是那种似懂非懂.....原理知道,但不会操作的感觉....)

 

关键就在于合并.,,,

只要递归搞到子树的重心....然后逐步往上跳  直至满足与当前树合并为重心.....

 

技术图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define MAXN 300005
using namespace std;

int n,q,tot;
int h[MAXN],ans[MAXN],f[MAXN],sz[MAXN];//以u为根的子树的重心  各点父亲  子树大小 

struct node{
    int from,to,next;
}e[MAXN<<1];

void init(){
    memset(h,-1,sizeof(h));
    memset(sz,0,sizeof(sz));
}

void add(int x,int y){
    tot++;
    e[tot].from=x;
    e[tot].to=y;
    e[tot].next=h[x];
    h[x]=tot;
}

int dfs(int now,int fa){
    f[now]=fa;
    sz[now]=1;
    ans[now]=now;
    for(int i=h[now];i!=(-1);i=e[i].next){
        if(e[i].to!=fa){
            dfs(e[i].to,now);
            sz[now]+=sz[e[i].to];
        }
    }
    for(int i=h[now];i!=(-1);i=e[i].next){
        if(e[i].to!=fa&&sz[e[i].to]*2>sz[now]){
            ans[now]=ans[e[i].to];
        }
    }
    while((sz[now]-sz[ans[now]])*2>sz[now]){
        ans[now]=f[ans[now]];
    }
}


int main(){
    cin>>n>>q;init();
    for(int i=2;i<=n;i++){
        int p;cin>>p;
        add(i,p);
        add(p,i);
    }    
    dfs(1,1);
    for(int i=1;i<=q;i++){
        int p;cin>>p;
        cout<<ans[p]<<endl;
    }
}
View Code

 

cf 686D - Kay and Snowflake

标签:ems   ++   操作   from   using   efi   nod   src   spl   

原文地址:https://www.cnblogs.com/shatianming/p/12297296.html

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