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

Posted tags:

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

题目链接:

http://codeforces.com/problemset/problem/685/B

题意:

给你n个点,以1为根,然后给你2-n的节点的父亲节点编号。问你每一颗子树的重心是哪一个节点。

思路:

有定理:把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上。 

考虑树的重心在哪个部分,一定是在当前节点u的最大子树v中,假设我们已经知道了子树v的重心ans[v],那么u的重心呢?就是在ans[v]这个节点到u的路径上。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MS(a) memset(a,0,sizeof(a))
#define MP make_pair
#define PB push_back
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
//////////////////////////////////////////////////////////////////////////
const int maxn = 3e5+10;

int n,q,fa[maxn],son[maxn],ans[maxn];
vector<int> g[maxn];

void dfs(int u){
    son[u] = 1;
    ans[u] = u;
    int mx = 0;
    for(int i=0; i<(int)g[u].size(); i++){
        int v = g[u][i];
        dfs(v);
        son[u] += son[v];
        if(son[v] > son[mx]) mx = v;
    }
    if(mx==0) return ;
    int now = ans[mx];
    while(son[now]*2<son[u]) now = fa[now];
    ans[u] = now;
}

int main(){
    cin >> n >> q;
    for(int i=2; i<=n; i++){
        cin >> fa[i];
        g[fa[i]].push_back(i);
    }
    dfs(1);
    for(int i=0; i<q; i++){
        int x = read();
        cout << ans[x] << endl;
    }

    return 0;
}

 

以上是关于Codeforces 686 D.Kay and Snowflake (dfs 树的重心)的主要内容,如果未能解决你的问题,请参考以下文章

CF 686D. Kay and Snowflake

codeforces 686A A. Free Ice Cream(水题)

CodeForces 686A Free Ice Cream (水题模拟)

codeforces 686B B. Little Robber Girl's Zoo(水题)

CodeForces 686B - Little Robber Girl's Zoo(暴力)

CodeForces 686B Little Robber Girl's Zoo (构造冒泡排序)