树形DP初步(2)补充例题

作为一个咸鱼中的咸鱼中的蒟蒻中的蒟蒻的OIer选手,今天看到小初一过来心里甚是高兴,终于有人比我弱了,于是我决定水一道题吓吓他们,结果……

点击传送:http://poj.org/problem?id=3107

又是全是英文快哭了心塞呀。

“没关系,题目的翻译版加简化版就是给定一棵树,求树的所有重心,按照编号从小到大的顺序输出。”zyy突然来到我的身边拍了我的肩膀说。

滚一边去!没错题目的意思就是zyy说的那样。在我们学校OJ就有这个解释,谁都知道。但做法呢?

学校OJ里介绍了这种做法:



分析:本题与上题基本上一样,只是求的量不同,既然我们在找树的重心的时候用的树型dp,而且是求的子树中节点数的最大值,然后求所有最

大值的最小值,那么就有可能存在多个重心,我们每更新到一个最小值的时候就记录其它的最小值也为这个最小值的重心,这样下去就会找到所

有的重心.


作为一个咸鱼OIer,看到后脑里就是懵。并竟我的信仰是:暴力出奇迹,骗分过样例!于是我灵机一动(好像有点怪怪的)产生了一种想法。不如我们开个数组记录每个点删去后最大子树的节点数。dfs完后扫一遍这个数组,如果等于最小值就输出,重要部分的代码长这样:



void dfs(int num)  
{  
    used[num] = 1;  
    d[num] = 0;  
    int max1 = 0;  
    for(int i=p[num];~i;i=a[i].next)  
        if(!used[a[i].to])  
        {  
             int u = a[i].to;
            dfs(u);  
            d[num] += d[u] ;  
            max1 = max(max1,d[u]);  
        }  
    d[num]=d[num]+1;
    max1 = max(max1,n-d[num]);
	max2[num]=max1;//记录最大子树 
    if(max1 < size || max1 == size && num < ans)   
        size = max1;  
}  

int main()  
{    
        init();  
        scanf("%d",&n);  
        for(int i=1;i<=n-1;i++)  
        {  
            int u,v;  
            scanf("%d%d",&u,&v);  
            add(u,v);  
            add(v,u);  
        }  
        dfs(1);  
        int k=0;
        //扫一遍 
        for(int i=1;i<=n-1;i++)
        if(max2[i]==size)b[++k]=i;
        for(int i=1;i<=k-1;i++)printf("%d ",b[i]);
		printf("%d\n",b[k]);  
    return 0;  
}  

做完了。

zyy:呵呵呵,我早做完了!

然而这只是小数据的做法。

大数据的以后补。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值