码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1655 Balancing Act (树形dp 树的重心)

时间:2015-07-22 14:38:49      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:poj   树形dp   树的重心   


Balancing Act
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 10596   Accepted: 4398

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

Source

POJ Monthly--2004.05.15 IOI 2003 sample task

题目链接:http://poj.org/problem?id=1655

题目大意:定义平衡数为去掉一个点其最大子树的结点个数,求给定树的最小平衡数和对应要删的点

题目分析:其实就是求树的重心,找到一个点,其所有的子树中最大的子树的节点数最少,那么这个点就是这棵树的重心,删除重心后,剩余的子树更加平衡正好满足题意,下面说明如何求重心,因为这是一棵无根树,因此要连双向边,任取一个顶点作为根,记dp[i]为以结点i为子树根的子树的结点个数(注意这里不包括子树根本身),所以
dp[i] += dp[son] + 1,加1是因为要算上其儿子自己这个结点,然后对于每个子树求出来的dp[son] + 1我要取最大,设最大为b,注意这里还要再取一次最大
b = max(b, n - dp[i] - 1),因为这是一棵无根树,当前结点i也可以做这棵树的根,所以这里把剩余部分也当作它的儿子(即在当前dfs序下的其祖先和兄弟部分)画个图可以看的更明白些


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 20005;
int const INF = 0x3fffffff;

struct EDGE
{
    int to, next;
}e[MAX * 2];

int head[MAX], dp[MAX];
bool vis[MAX];
int n, cnt, num, ans, b;

void Add(int u, int v)
{
    e[cnt].to = v;
    e[cnt].next = head[u];
    head[u] = cnt ++;
}

void Init()
{
    cnt = 0;
    n = 0;
    num = INF;
    ans = n;
    memset(head, -1, sizeof(head));
    memset(dp, 0, sizeof(dp));
    memset(vis, false, sizeof(vis));
}

void DFS(int rt)
{
    vis[rt] = true;
    dp[rt] = 0;
    int b = 0;
    for(int i = head[rt]; i != -1; i = e[i].next)
    {
        int son = e[i].to;
        if(!vis[son])
        {
            DFS(son);
            dp[rt] += dp[son] + 1;
            b = max(b, dp[son] + 1); 
        }
    }
    b = max(b, n - dp[rt] - 1);
    if(b < num || (b == num && rt < ans))
    {
        num = b;
        ans = rt;
    }
    return; 
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        Init();
        int st;
        scanf("%d", &n);
        for(int i = 0; i < n - 1; i++)
        {
            int u, v;
            scanf("%d %d", &u, &v);
            Add(v, u);   
            Add(u, v);
            st = u;
        }
        DFS(st);
        printf("%d %d\n", ans, num);
    }
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

POJ 1655 Balancing Act (树形dp 树的重心)

标签:poj   树形dp   树的重心   

原文地址:http://blog.csdn.net/tc_to_top/article/details/47001925

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!