zoukankan      html  css  js  c++  java
  • [BZOJ1131/POI2008]Sta树的深度

    Description
      给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大


    Input
      给出一个数字N,代表有N个点.N<=1000000 下面N-1条边.


    Output
      输出你所找到的点,如果具有多个解,请输出编号最小的那个.


    Sample Input
    8
    1 4
    5 6
    4 5
    6 7
    6 8
    2 4
    3 4

    Sample Output
    7

    题解:

      都说是裸树形DP,其实我做的时候就是把它当成搜索去做了,当然是一个意思。假设当前的根为1,先求出每棵子树的大小,以及所有点的深度之和。考虑到我们换根会带来的影响,一部分点的深度会减小,一部分点的深度会增加。故假设我们当前在第i号节点,递归到他的一个儿子节点j,则总深度的变化为以第i号节点所有儿子节点的子树的节点和减去剩余的节点和。故把所有节点的情况都考虑一次,最后求出最大值就行了。

      但是,有一个很坑的地方,如果你是用的Windows,用DFS基本上是没有戏了,因为节点数量很多,在Windows环境下不能开启无限栈,所以还是用BFS吧,当然你也可以手写栈,但是没必要作死。

    代码(本地非官方数据83分,用的DFS):

    --------------------------------------------------------------------------------------------------

    #include <cstdio>
    #define MAXN 1000005

    int max(int a, int b) { return a > b ? a : b; }

    struct Edge { int v, next; } edge[MAXN << 1];

    int n, u, v, tot[MAXN], now, h[MAXN];
    int fa[MAXN], siz[MAXN], ans, maxt;

    void addEdge(int u, int v) { now++, edge[now] = (Edge) {v, h[u]}, h[u] = now; }

    void DFS(int o)
    {
      siz[o] = 1;
      for (int x = h[o]; x; x = edge[x].next)
      {
        int v = edge[x].v;
        if (v != fa[o]) fa[v] = o, DFS(v), siz[o] += siz[v], tot[o] += tot[v] + siz[o];
      }
    }

    void DFS2(int o)
    {
      if (o != 1) tot[o] = tot[fa[o]] - siz[o] * 2 + n;
      for (int x = h[o]; x; x = edge[x].next)
      {
        int v = edge[x].v;
        if (v != fa[o]) DFS2(v);
      }
    }

    int main()
    {
      freopen("sta.in", "r", stdin);
      freopen("sta.out", "w", stdout);
      scanf("%d", &n);
      for (int i = 1; i <= n - 1; i++)
        scanf("%d %d", &u, &v), addEdge(u, v), addEdge(v, u);
      DFS(1), DFS2(1);
      for (int i = 1; i <= n; i++)
        if (maxt < tot[i]) maxt = tot[i], ans = i;
      printf("%d", ans);

    }

    --------------------------------------------------------------------------------------------------

  • 相关阅读:
    正则表达式
    Java 枚举(enum) 详解7种常见的用法
    【20170921】(Unfinished)2017暑假北京学习 day 2
    (Unfinished)2017暑假北京学习 day 2
    Openjudge NOI题库 数论4975 两只鼹鼠
    Openjudge NOI题库 数论185 反正切函数的应用
    Noip1998 提高组3 卢斯加法表
    【自己的小玩具程序】化学方程式配平【测试中】【未完成】
    Code Vs 1010 过河卒
    NOI 练手题 图像旋转翻转变换
  • 原文地址:https://www.cnblogs.com/jinkun113/p/4899038.html
Copyright © 2011-2022 走看看