POJ 1655 Balancing Act (求树的重心)树形DP(经典)

Posted 00isok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1655 Balancing Act (求树的重心)树形DP(经典)相关的知识,希望对你有一定的参考价值。

<题目链接>

题目大意:
给你一棵树,任意去除某一个点后,树被分成了几个联通块,则该点的平衡值为所有分成的连通块中,点数最大的那个,问你:该树所有点中,平衡值最小的那个点是什么?

解题分析:

运用递归,找到以u为根节点,所有子节点数的最大值,然后求出这些最大值的最小值。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 20010;
struct Edge
{
    int to,next;
}edge[MAXN*2];

int head[MAXN],tot;
void init()
{
    memset(head,-1,sizeof(head));
    tot = 0;
}
void addedge(int u,int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
int dp[MAXN],num[MAXN];
int n;

void dfs(int u,int pre)
{
    dp[u] = 0;num[u] = 1;
    for(int i = head[u];i != -1;i = edge[i].next)
    {
        int v = edge[i].to;
        if(v == pre)continue;        //如果下一个点是u的父亲(即刚刚走过的点),那么跳过,防止下一步dfs(v,u)遍历该无向图时,不停的在两个点之间来回遍历
        dfs(v,u);          //继续从它的子节点开始向下搜索 
        dp[u] = max(dp[u],num[v]);   //dp[u]指的是u的每个子节点方向所对应的最大节点数的最大值 
        num[u] += num[v];           
    }
    //num[u]此时代表除父节点方向外的所有子节点数(包括它本身,,因为num[u]初始化为1)
    dp[u] = max(dp[u],n - num[u]);     //n-num[u]指的是dp[u]父节点方向的节点数
}

int main()
{
    int T;
    scanf("%d",&T);
    int u,v;
    while(T--)
    {
        scanf("%d",&n);
        init();
        for(int i = 1;i < n;i++)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        dfs(1,-1);

        int ans1 = 1, ans2 = dp[1];      //找到去除该点后,所得连通分量最大点数的最小值,即寻找平衡点
        for(int i = 2;i <= n;i++)
            if(ans2 > dp[i])
            {
                ans1 = i;
                ans2 = dp[i];
            }
        printf("%d %d
",ans1,ans2);
    }
    return 0;
}

 

 

2018-08-17

 


以上是关于POJ 1655 Balancing Act (求树的重心)树形DP(经典)的主要内容,如果未能解决你的问题,请参考以下文章

poj1655 Balancing Act

[POJ1655]Balancing Act

POJ - 1655 Balancing Act (树的重心)

Balancing Act(poj1655)

poj 1655 Balancing Act

POJ 1655Balancing Act