zoukankan      html  css  js  c++  java
  • ICPC2019徐州 现场赛M Kill the tree 树的重心

    链接

    给你一颗以1为根,2^5的树。让你求出以每个点为根的子树中,到子树中每个点距离和最小的点。

    首先先做条件转化,到子树中每个点距离和最小,等价于重心,所以问题变成了求每棵子树的重心。

    我们考虑如果用子树重心求出父亲的重心。发现一个显而易见的结论,父亲子树的重心,一定在重儿子子树的重心到根的连线上。

    我们先做dfs,求出siz和重儿子。然后再做一遍dfs,每次从重儿子的重心往上爬,爬到再爬一步,最大子树会变大为止。这时看下取当前点和其重儿子答案是否相同,如果相同则重心有两个,为当前点和重儿子。否则重心只有一个,为当前点。

     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 const int MAXN = 210000;
     5 int n,cnt;
     6 int head[MAXN],siz[MAXN],fa[MAXN],son[MAXN],ans[MAXN][2],to[2 * MAXN],nxt[2 * MAXN];
     7 void dfs1(int x)
     8 {
     9     siz[x] = 1;
    10     for (int i = head[x];i;i = nxt[i])
    11     {
    12         if (to[i] == fa[x])
    13             continue;
    14         fa[to[i]] = x;
    15         dfs1(to[i]);
    16         siz[x] += siz[to[i]];
    17         if (siz[to[i]] > siz[son[x]])
    18             son[x] = to[i];
    19     }
    20 }
    21 void dfs2(int x)
    22 {
    23     for (int i = head[x];i;i = nxt[i])
    24     {
    25         if (to[i] == fa[x])
    26             continue;
    27         dfs2(to[i]);
    28     }
    29     int t = ans[son[x]][0];
    30     if (t == 0)
    31         t = x;
    32     while (t != x && max(siz[son[t]],siz[x] - siz[t]) >= max(siz[son[fa[t]]],siz[x] - siz[fa[t]]))
    33         t = fa[t];
    34     ans[x][0] = t;
    35     if (max(siz[son[t]],siz[x] - siz[t]) == max(siz[son[son[t]]],siz[x] - siz[son[t]]))
    36         ans[x][1] = son[t];
    37 }
    38 void add(int x,int y)
    39 {
    40     nxt[++cnt] = head[x];
    41     to[cnt] = y;
    42     head[x] = cnt;
    43 }
    44 int main()
    45 {
    46     scanf("%d",&n);
    47     int tx,ty;
    48     for (int i = 1;i <= n - 1;i++)
    49     {
    50         scanf("%d%d",&tx,&ty);
    51         add(tx,ty);
    52         add(ty,tx); 
    53     }
    54     dfs1(1);
    55     dfs2(1);
    56     for (int i = 1;i <= n;i++)
    57     {
    58         if (ans[i][1] != 0 && ans[i][1] < ans[i][0])
    59             swap(ans[i][1],ans[i][0]);
    60         printf("%d",ans[i][0]);
    61         if (ans[i][1] != 0)
    62             printf(" %d
    ",ans[i][1]);
    63         else
    64             printf("
    ");
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    实验四 决策树算法及应用
    实验三 朴素贝叶斯算法及应用
    实验二 K近邻算法及应用
    实验一 感知器及其应用
    实验三 面向对象分析与设计
    实验二 结构化分析与设计
    实验一 软件的开发文档与工具的安装与使用
    ATM管理系统
    举例分析流程图与活动图的区别与联系
    四则运算
  • 原文地址:https://www.cnblogs.com/iat14/p/12252812.html
Copyright © 2011-2022 走看看