树的统计

    原题:一颗含有n个结点的树,所有的结点依次编号为1,2,3,……,n.对于编号为v的结点,定义t(v)为v的后代中所有编号小于v的结点个数。输入这棵树,请输出t(1),t(2),t(3),……,t(n)。

 

    当然,对于本题,写出一个O(n2)的算法是一件很容易的事,这显然也不是接下来要推出的理想算法。

    先深度优先遍历该树,按照访问的先后顺序排列结点:7 10 14 12 13 1 9 11 6 5 8 3 15 12 4(DFS序列)。然后把每个结点的子结点先后顺序反转,重新遍历,可得到新的排序结点序列:7 4 3 12 15 9 6 8 5 11 1 10 14 13 2(逆DFS序列)。以结点9为代表,显然,把两次遍历过程中在结点9之后被访问的点圈出来,得到下图。

 

 

    不难发现,两个线框的重叠区域,即为结点9的所有后代结点。看到上面的图,估计有组合数学知识的人都能想到容斥原理。上图中除了线框1和2包括的部分,还包括了结点9本身和它的直系祖先结点。

    定义f(v,S)表示在S所描述的集合中,结点编号小于v的个数。则对于9号结点,有:
    f(9,线框1)+f(9,线框2)+f(9,9的直系祖先)-f(9,整棵树)=f(9,9的后代)

    推广到更一般的情况,有

    f(v,DFS序列中v之后的部分)+f(v,逆DFS序列中v之后的部分)+f(v,v的直系祖先)-f(v,整棵树)=f(v,v的后代)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值