cf 686D - Kay and Snowflake

Posted shatianming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf 686D - Kay and Snowflake相关的知识,希望对你有一定的参考价值。

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

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

考虑树的重心的性质

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的主要内容,如果未能解决你的问题,请参考以下文章

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

CodeForces 685B Kay and Snowflake

Codeforces 686 D - Kay and Snowflake

codeforces 685B Kay and Snowflake 树的重心

Codeforces 686 D.Kay and Snowflake (dfs 树的重心)

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