zoukankan      html  css  js  c++  java
  • POJ 1655 Balancing Act (树状dp入门)

    Description

    Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the largest tree in the forest T created by deleting that node from T.
    For example, consider the tree:

    Deleting node 4 yields two trees whose member nodes are {5} and {1,2,3,6,7}. The larger of these two trees has five nodes, thus the balance of node 4 is five. Deleting node 1 yields a forest of three trees of equal size: {2,6}, {3,7}, and {4,5}. Each of these trees has two nodes, so the balance of node 1 is two.

    For each input tree, calculate the node that has the minimum balance. If multiple nodes have equal balance, output the one with the lowest number.

    Input

    The first line of input contains a single integer t (1 <= t <= 20), the number of test cases. The first line of each test case contains an integer N (1 <= N <= 20,000), the number of congruence. The next N-1 lines each contains two space-separated node numbers that are the endpoints of an edge in the tree. No edge will be listed twice, and all edges will be listed.

    Output

    For each test case, print a line containing two integers, the number of the node with minimum balance and the balance of that node.

    Sample Input

    1
    7
    2 6
    1 2
    1 4
    4 5
    3 7
    3 1
    

    Sample Output

    1 2

    就是给你一棵树,让你在树上去掉一个节点,这样就形成了许多子树,设所有子树中点个数最多的那颗子树的点的个数为x,现在让这个x最小,问你应该剪掉哪个节点,x是多少?
    根据树形结构的特殊性,从树根走到叶子节点是严格按照层次顺序的。我现在就开始做dp。首先我们先定义一个dp数组。
    我们还需要一个num[x]数组,用来表示以x为树根的子树上有多少节点

    对于每一个节点,去掉它所得到的x的值是什么呢?1.它所有子节点为根的子树的最大值 2.除了x和它下面所有的子树,剩下全部的节点。这两者比较最大值就可以了。

    刚刚看了白书,就是让找树的重心。
    代码如下:
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 using namespace std;
     6 #define M 20020
     7 int n;
     8 struct Node
     9 {
    10     int to,pre;
    11 }edge[M*2];
    12 int head[M],tot,dp[M],num[M];
    13 void init ()
    14 {
    15     memset(head,-1,sizeof head);
    16     tot=0;
    17 }
    18 void addedge (int u,int v)
    19 {
    20     edge[tot].to=v;
    21     edge[tot].pre=head[u];
    22     head[u]=tot++;
    23 }
    24 void dfs (int u,int prenode)
    25 {
    26     dp[u]=0;
    27     num[u]=1;
    28     for (int i=head[u];i!=-1;i=edge[i].pre)
    29     {
    30         int v=edge[i].to;
    31         if (v==prenode)
    32         continue;
    33         dfs(v,u);
    34         dp[u]=max(dp[u],num[v]);
    35         num[u]+=num[v];
    36     }
    37     dp[u]=max(dp[u],n-num[u]);
    38 }
    39 int main()
    40 {
    41     int t;
    42     scanf("%d",&t);
    43     while (t--)
    44     {
    45         scanf("%d",&n);
    46         init();
    47         for (int i=1;i<n;++i)
    48         {
    49             int u,v;
    50             scanf("%d %d",&u,&v);
    51             addedge(u,v);
    52             addedge(v,u);
    53         }
    54         dfs(1,-1);
    55         int ans1=1,ans2=dp[1];
    56         for (int i=2;i<=n;++i)
    57         {
    58             if (ans2>dp[i])
    59             {
    60                 ans1=i;
    61                 ans2=dp[i];
    62             }
    63         }
    64         printf("%d %d
    ",ans1,ans2);
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    Oracle查询语句中指定索引时优化器及指定索引不好使的处理方法
    oracle 死锁处理
    ORACLE里锁的几种模式
    oracle rpad()函数
    Oracle JOB
    Oracle 函数取汉字的拼音首字母
    COM 组件注册方法
    oracle 创建一个用户,只能访问指定的对象
    SOAP和WSDL的一些必要知识
    【转】net.sf.json.JSONException: java.lang.reflect.InvocationTargetException
  • 原文地址:https://www.cnblogs.com/agenthtb/p/5948396.html
Copyright © 2011-2022 走看看