Codeforces 686 D Kay and Snowflake (树重心)

来源:互联网 发布:人工智能三贤者理论 编辑:程序博客网 时间:2024/05/17 02:47

题意

给出n个节点的树和q个查询(范围均为3e5),对每个查询输出x为根节点的子树的重心。

思路

树的重心有几个很好用的性质,下文参考这里
1.树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么他们的距离和一样。
2.把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上。
3.把一个树添加或删除一个叶子,那么它的重心最多只移动一条边的距离。
由第二个性质就能得到某个树的重心和他的重儿子的重心一定是在重链上,即假设v是u的重儿子,从v的重心网上找找到u,u的重心一定在这中间,这里暴力找就行了,因为就算是最坏的一条重链也是复杂度正确的。

代码

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;#define LL long long#define Lowbit(x) ((x)&(-x))#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1|1#define MP(a, b) make_pair(a, b)const int INF = 0x3f3f3f3f;const int MOD = 1000000007;const int maxn = 100000 + 7;const double eps = 1e-8;const double PI = acos(-1.0);typedef pair<int, int> pii;int n, q, x;int fa[3*maxn];int sz[3*maxn];int ans[3*maxn];vector<int> G[3*maxn];void dfs(int u){    sz[u] = 1;    ans[u] = u;    int mmax = 0;    //重儿子    for (int i = 0; i < G[u].size(); i++)    {        int v = G[u][i];        dfs(v);        sz[u] += sz[v];        if (sz[v] > sz[mmax])            mmax = v;    }    if (sz[mmax] * 2 > sz[u])    {        //printf("2333 %d\n", u);        int now = ans[mmax];        while ((sz[u] - sz[now]) * 2 > sz[u])            now = fa[now];        ans[u] = now;    }}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    scanf("%d%d", &n, &q);    for (int i = 2; i <= n; i++)    {        scanf("%d", &fa[i]);        G[fa[i]].push_back(i);    }    dfs(1);    while (q--)    {        scanf("%d", &x);        printf("%d\n", ans[x]);    }    return 0;}
0 0
原创粉丝点击