树形动态规划 例题POJ3107

本文转载至:http://zhexue.sinaapp.com/?p=104

题目来源:POJ3107

给定一棵无根树,删除树中一个节点,剩下各子树的包含的节点数最大值最小,问树中有多少个这样的节点?
解法:任意选择一个节点,作为根,进行遍历。对一个节点V,设其子节点为cv[1..k],f[v]为以节点v为根的子树包含的节点数。
对于每一个节点V,删除V之后剩下子树含有的节点数中最大分别为 max{ f[cv[1]],f[cv[2]],....f[cv[k]],SumNode-(f[cv[1]]+f[cv[2]]+....+f[cv[k]]) },一次遍历即可求出所有删除一个节点后的最大子树包含的节点数。

#include < iostream >
#include
< vector >
#include
< algorithm >
#include
< stdio.h >
#define MAXN 50005
using   namespace std;
vector
< int > ansNode;
int maxNumNode;
int n, f[MAXN];
int pointTree[MAXN];
struct Tree{
   
int x,y;
}tree[MAXN
* 2 ];
int len;
bool cmp( struct Tree a, struct Tree b)
{
   
return a.x < b.x;
}
int treedp( int parentNode, int thisNode){
   
int maxNode = 0 ;
   
int sumChildNode = 0 ;
   
int index = pointTree[thisNode];
   
do {
       
int childNode = tree[index].y;
       
if (childNode != parentNode)
        {
            f[childNode]
= treedp(thisNode,childNode);
            sumChildNode
+= f[childNode];
           
if (f[childNode] > maxNode)maxNode = f[childNode];
        }
        index
++ ;
    }
while (index < len && tree[index].x == tree[index - 1 ].x);
   
if (maxNode < n - sumChildNode - 1 )maxNode = n - sumChildNode - 1 ;
   
if (maxNode < maxNumNode){
        maxNumNode
= maxNode;
        ansNode.clear();
        ansNode.push_back(thisNode);
    }
else   if (maxNode == maxNumNode){
        ansNode.push_back(thisNode);
    }
   
return sumChildNode + 1 ;
}

int main( int argc, int   * argv[])
{
   
while (scanf( " %d " , & n) != EOF){
        len
= 0 ;
       
for ( int i = 1 ;i < n;i ++ ){
           
int x,y;
            scanf(
" %d%d " , & x, & y);
            tree[len].x
= x;
            tree[len
++ ].y = y;
            tree[len].x
= y;
            tree[len
++ ].y = x;
        }
        sort(tree,tree
+ len,cmp);
        pointTree[tree[
0 ].x] = 0 ;
       
for ( int i = 1 ;i < len;i ++ ){
           
if (tree[i].x != tree[i - 1 ].x)
                pointTree[tree[i].x]
= i;
        }
        ansNode.clear();
        maxNumNode
= n;
        treedp(
- 1 , 1 );
        sort(ansNode.begin(),ansNode.end());
       
for ( int i = 0 ;i < ansNode.size();i ++ )
            printf(
" %d " ,ansNode[i]);
    }
   
return   0 ;
}

转载于:https://www.cnblogs.com/zhexue/archive/2011/12/25/2301279.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值