zoukankan      html  css  js  c++  java
  • poj1655 Balancing Act(树的重心[模板])

    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

    分析:
    实际上这就是找树的重心

    树的重心:
    找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。

    树的重心可以通过简单的两次搜索求出,
    第一遍搜索求出每个结点的子树大小son[u]
    第二遍搜索找出使max{son[u],n-son[u]-1}最小的结点。

    实际上这两步操作可以在一次遍历中解决。
    对结点u的每一个儿子v,递归的处理v,求出son[v]
    找到最大子树,处理完所有子结点后,判断u是否为重心。

    还有一种方法,虽然不能保证求出来的一定是重心,但是能找到一个结点,而这个以这个结点为根的话,所有的子树的结点数量都不会超过总结点数的一半。

    同样是先搜索出son[u],从某个假设的根开始向下找,如果有子结点v,使son[v]>son[u]/2,就以v作为新的根,重复执行,直到没有满足条件的子结点。

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int INF=0x33333333;
    const int N=20010;
    int n;
    struct node{
        int x,y,nxt;
    };
    node way[N<<1];
    int st[N],tot,son[N],siz,ans;
    bool p[N];
    
    void add(int u,int w)
    {
        tot++;
        way[tot].x=u;way[tot].y=w;way[tot].nxt=st[u];st[u]=tot;
        tot++;
        way[tot].x=w;way[tot].y=u;way[tot].nxt=st[w];st[w]=tot;
    }
    
    void dfs(int now,int fa)
    {
        son[now]=1;
        int maxx=0;
        for (int i=st[now];i;i=way[i].nxt)
        {
            int y=way[i].y;
            if (y!=fa&&p[y])
            {
                p[y]=0;
                dfs(y,now);
                son[now]+=son[y];
                maxx=max(maxx,son[y]);   //找到最大的儿子 
            }
        }
        maxx=max(maxx,n-son[now]);
        if (maxx<siz)
        {
            siz=maxx;ans=now;
        }
        else if (maxx==siz) ans=min(ans,now);
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d",&n);
            memset(st,0,sizeof(st));
            tot=0;
            for (int i=1;i<n;i++)
            {
                int u,w;
                scanf("%d%d",&u,&w);
                add(u,w);
            }
            memset(son,0,sizeof(son));
            memset(p,1,sizeof(p));
            ans=0;
            siz=INF;
            p[1]=0;
            dfs(1,0);
            printf("%d %d
    ",ans,siz);
        }
        return 0;
    }
  • 相关阅读:
    Spring异常重试框架Spring Retry
    Ubuntu 16.04无法在WPS中输入中文的问题解决
    Ubuntu 16.04使用百度云的方案
    Ubuntu 16.04安装Wine版的迅雷+QQ(完美方案,终极解决方法)
    Ubuntu下Deb软件包相关安装与卸载
    Spring在Java Filter注入Bean为Null的问题解决
    MyBatis 3在Insert之后返回主键
    MySQL JDBC URL参数(转)
    MySQL索引原理及慢查询优化
    Markdown 语法整理大集合2017
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673148.html
Copyright © 2011-2022 走看看