首页 > 其他 > 详细

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

时间:2019-11-04 21:54:53      阅读:81      评论:0      收藏:0      [点我收藏+]

 

[传送门]

 

来填徐州 M 题的坑了...

M 题题面叙述的就是求子树的重心...

百度百科对树的重心的介绍...

树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个重心,他们的距离和一样。
把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
一棵树最多有两个重心,且相邻。

然后还有两个性质,一个是一棵树的重心一定在最大子树的重心到根的路径上。

第二个就是判断是否为重心就是以其为根的所有子树的size都不超过整个树的size的二分之一。

然后就做完了...

技术分享图片
#include <bits/stdc++.h>

const int N = 3e5 + 7;
std::vector<int> vec[N];
int cen[N], sz[N], fa[N], heavy[N], pre[N];
int n, q;

bool iscen(int u, int v) {
    return (sz[u] - sz[v]) * 2 <= sz[u] && heavy[v] * 2 <= sz[u];
}

void dfs1(int u, int pre) {
    fa[u] = pre;
    sz[u] = 1;
    for (int v: vec[u]) {
        dfs1(v, u);
        sz[u] += sz[v];
        heavy[u] = std::max(heavy[u], sz[v]);
    }
}

void dfs2(int u) {
    if (sz[u] == 1) {
        cen[u] = u;
        return;
    }
    int mx = vec[u][0];
    for (int v: vec[u]) {
        dfs2(v);
        if (sz[mx] < sz[v]) mx = v;
    }
    int c = cen[mx];
    while (!iscen(u, c))
        c = fa[c];
    cen[u] = c;
}

int main() {
    scanf("%d%d", &n, &q);
    for (int i = 2; i <= n; i++) {
        int u;
        scanf("%d", &u);
        vec[u].push_back(i);
    }
    dfs1(1, 0);
    dfs2(1);
    for (int u; q--; ) {
        scanf("%d", &u);
        printf("%d\n", cen[u]);
    }
    return 0;
}
View Code

 

 

 

 

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

原文:https://www.cnblogs.com/Mrzdtz220/p/11794483.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!