• Codeforces 1111 E. Tree(虚树,DP)


    题意

    有一棵树,q个询问,每次询问,指定一个点做树根,再给定k个点,要求把这些点分成不超过m组的方案数,分配的限制是任意两个有祖先关系的点不能分在同一组。题目还保证了所有的询问的k加起来不超过1e5。 ## 思路 如果直接在原树上DP计数,那么q次询问下的DP总复杂度是平方级别的,显然不对。 由于询问点数的总和很少,所以考虑在虚树上计数。(不了解虚树的可以先学习一下,大概思想是根据询问的点来重新建一颗包含关键信息,但是规模较小的树)于是多次询问的问题就解决了。 难点转到考虑虚树上的dp计数。我们按照dfs序来dp,定义f[i][j]表示遍历到的前i个点分成j组的方案数,cnt[i]表示点i到根有多少个询问点。 那么对于f[i][j]: ①如果j<=cnt[i],也就说明光是把i的祖先们分开就需要用到j个组了,那么此时点i必然无组可放,也就是说此时没有方案行得通,于是f[i][j]=0; ②否则,f[i][j]=f[i-1][j-1]+f[i-1][j]*(j-cnt[i]).这个应该不难理解,我们是按照dfs序来dp的,dp到点i时其祖先一定已经更新完了。那么对于新来的点i,它要么新开一组,方案数为f[i-1][j-1],要么加入到已有的组中,方案数为f[i-1][j]*(j-cnt[i]),(即从已有的组中扣去那些祖先所在的组)。 考虑到空间有点吃紧,可以滚动dp,当然精打细算一点,开二维数组来DP的空间也正好够。 ## 代码 ``` #include #define dd(x) cout<<#x<<" = "<
  • 相关阅读:
    将博客搬至CSDN
    mplayer的执行过程分析(本地、网络)
    ES6新特性概览
    ES6 块级作用域
    echarts各种字体颜色的修改
    js时间格式转换为几天前几小时几分钟等
    正则验证非法字符
    JS阻止事件冒泡函数
    cookie设置,读取,删除
    C/C++基础(三)
  • 原文地址:https://www.cnblogs.com/orangee/p/10543208.html
Copyright © 2020-2023  润新知