题目链接

题意:
给你一棵nnn个点的树,nnn是偶数,把这些点分成n2\frac{n}{2}2n​个点对,每个点对会把路径上的所有边覆盖,问你每条边至少覆盖一次有多少种配对方式。n&lt;=5000n&lt;=5000n<=5000

题解:
又是我看题解都半天看不懂的题。算是一道比较神仙的计数题。题解上来就说考虑容斥,结果我很久才明白那个容斥是在干什么。感觉现在也不是很明白,所以可能题解中有诸多错误,还请斧正。

做法是这样的,我们发现,如果给你一棵树,你让里面的点随意两两配对,这个方案数是可以算的,我们记作ggg。计算的方法是,显然只有点数为偶数时才会有合法的配对方案,这个方案数是(n−1)∗(n−3)∗...∗1(n-1)*(n-3)*...*1(n−1)∗(n−3)∗...∗1,原因是一开始随便找一个点,有(n−1)(n-1)(n−1)个点可以和它配对,由于选其他的点出来时的最后配对方案会与当前随便找的这个点的某个方案重复,也就是这时候选出的每一个点都是等价的,所以并不去乘nnn,下只有n−2n-2n−2个点没有用过了,那么我们再拿出一个,就有n−3n-3n−3种可能。以此类推,就可以得到求ggg的这个式子,所以我们就可以把ggg给预处理出来。

我们设f(S)f(S)f(S)为SSS这个集合的边都没有被覆盖到,并且每个连通块内部随意配对的方案数,我们可以发现,这些没有被覆盖的边把树划分成了∣S∣+1|S|+1∣S∣+1个连通块,为了保证这些边不被覆盖,每个连通块只能内部配对,所以我们令f(S)=∏i=1∣S∣+1g(size[i])f(S)=\prod_{i=1}^{|S|+1}g(size[i])f(S)=∏i=1∣S∣+1​g(size[i]),其中sizesizesize表示连通块大小。

根据容斥原理,我们要求的答案就是∑S⊆E(−1)∣S∣f(S)\sum_{S\subseteq E}(-1)^{|S|}f(S)∑S⊆E​(−1)∣S∣f(S)。我按我的理解来解释一下这个式子,就是利用容斥,我们用所有都随意配对的方案数,减去只有一条边没有覆盖,其余随意配对的方案数,此时有两条边没有覆盖的那些方案会在那两条边的地方各减去一次,所以要加回来一次,也就是加上有两条边没有被覆盖,其余随便配对的方案,以此类推。

我们不能直接暴力枚举SSS算答案,我们考虑用树形dp来算出最终答案。我们设dp[x][i]dp[x][i]dp[x][i]为在xxx这个点,还有iii个子树内的点没有匹配的方案数。我们转移时枚举子树,先算出新的dp值,再更新当前点的size,算dp值的时候枚举之前还剩多少点没有匹配,新的子树内又提供了多少没有匹配的点。我们需要特别处理dp[x][0]dp[x][0]dp[x][0],因为这时候所有点都在子树内部匹配了,我们枚举已经处理好了所有不超过size[x]size[x]size[x]偶数,统计答案时要乘上一个ggg,表示那种情况下的所有方案,还要再乘一个−1-1−1,表示所有点在子树内相互匹配了,所以当前点到这棵子树的这条边就一定没法被覆盖了,比之前又多了一条没被覆盖的边,容斥系数变为原来的相反数。我们设根节点是1号节点,最后答案就是dp[1][0]∗(−1)dp[1][0]*(-1)dp[1][0]∗(−1)。这里乘−1-1−1的原因我感觉是1号点是根,没有父节点了,也就不会多出一条没被覆盖的边,但是在计算的时候还是按照有多出了一条没被覆盖的边计算的,所以最后理应不乘-1,这里再乘一次-1,就变回应有的结果了。我感觉这个树形dp的本质应该是在对于没有覆盖的边数进行容斥,并不是在按点对的配对情况dp。

总之我是真的看不懂各位神仙写的题解啊,可能过两天还会再研究一下。

update:
请教了chaojidouding大神这个题的做法,感觉他的做法与我之前写的稍有不同,但是好理解不少。
他的做法设dp[x][i][0/1]dp[x][i][0/1]dp[x][i][0/1]表示在xxx的子树内,有iii个点没有被匹配,有偶数/奇数条边没有被覆盖的方案数(因为容斥系数只与边数的奇偶性有关)。dp转移的方法和我类似,他的写法是最后再乘ggg,然后在算完之后统计根节点的答案。

放两个他的核心代码的片段(完整版是可以在atcoder上找到的):

我的做法的代码:

#include <bits/stdc++.h>
using namespace std;int n,hed[5010],sz[5010],cnt;
long long f[5010][5010],g[5010],dp[5010];
const long long mod=1e9+7;
struct node
{int to,next;
}a[200010];
inline void add(int from,int to)
{a[++cnt].to=to;a[cnt].next=hed[from];hed[from]=cnt;
}
inline void dfs(int x,int fa)
{sz[x]=1;f[x][1]=1;for(int i=hed[x];i;i=a[i].next){int y=a[i].to;if(y==fa)continue;dfs(y,x);for(int j=0;j<=sz[x]+sz[y];++j)dp[j]=0;for(int j=1;j<=sz[x];++j){for(int k=0;k<=sz[y];++k){dp[j+k]=(dp[j+k]+f[x][j]*f[y][k]%mod)%mod;}}sz[x]+=sz[y];for(int j=1;j<=sz[x];++j)f[x][j]=dp[j];}for(int i=2;i<=sz[x];i+=2)f[x][0]=(f[x][0]+mod-f[x][i]*g[i]%mod)%mod;
}
int main()
{scanf("%d",&n);for(int i=1;i<=n-1;++i){int x,y;scanf("%d%d",&x,&y);add(x,y);add(y,x);}g[0]=1;for(int i=2;i<=n;i+=2)g[i]=g[i-2]*(i-1)%mod;dfs(1,0);printf("%lld\n",(mod-f[1][0])%mod);return 0;
}

ARC101E Ribbons on Tree 树形dp 容斥相关推荐

  1. AT4352-[ARC101C] Ribbons on Tree【dp,容斥】

    正题 题目链接: https://www.luogu.com.cn/problem/AT4352 https://atcoder.jp/contests/arc101/tasks/arc101_c 题 ...

  2. ARC101E - Ribbons on Tree 树形DP

    题意 在一个有nnn个点的树上,nnn为偶数,把所有的点两两配对,配对点之间的路径染色,求把树上所有路径染色的方案数,对1e9+71e9 + 71e9+7取模 这个题完全想不出来 最后还是RudyGa ...

  3. P5405-[CTS2019]氪金手游【树形dp,容斥,数学期望】

    前言 话说在LojLojLoj下了个数据发现这题的名字叫fgofgofgo 正题 题目链接:https://www.luogu.com.cn/problem/P5405 题目大意 nnn张卡的权值为1 ...

  4. [LOJ#3124][CTS2019]氪金手游(概率 + 树形 DP + 容斥)

    Address 洛谷 P5405 LOJ #3124 Solution 先考虑如果以某个点(下面定为 111 )为根时,如果所有的限制二元组 (u,v)(u,v)(u,v) 都满足 uuu 是 vvv ...

  5. ARC101E Ribbons on Tree 容斥原理+dp

    题目链接 https://atcoder.jp/contests/arc101/tasks/arc101_c 题解 直接容斥.题目要求每一条边都被覆盖,那么我们就容斥至少有几条边没有被覆盖. 那么没有 ...

  6. BZOJ4455 / UOJ185 小星星 —— 树形dp + 容斥

    题目链接:点我啊╭(╯^╰)╮ 题目大意: nnn 个点 mmm 条边的图     破坏后现在变成 nnn 个点的树     问这颗树每个点映射回原来的图的总方案数     映射即现在的两点存在边,原 ...

  7. bzoj 4455 [Zjoi2016]小星星 树形dp容斥

    4455: [Zjoi2016]小星星 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 643  Solved: 391 [Submit][Statu ...

  8. [BZOJ4455][UOJ185][Zjoi2016]小星星(树形DP+容斥)

    将问题抽象化: 一个nnn个节点的树,和一个n" role="presentation" style="position: relative;"> ...

  9. P3349-[ZJOI2016]小星星【树形dp,容斥】

    正题 题目链接:https://www.luogu.com.cn/problem/P3349 题目大意 nnn个点的一棵树,再给出一张图,树上每个点对应图上每个点后要求树上的边图上都有,求有多少种对应 ...

最新文章

  1. 在Linux下如何安装配置SVN服务
  2. Bitlocker企业安全加密管理系列-2
  3. 修改labelImg软件的yolo标注写入格式(.txt文件不换行的解决办法)(将换行符'\n'替换成'\r\n')
  4. AlvinZH双掉坑里了
  5. IE6PNG8PNG24test
  6. Morph-UGATIT:一种支持渐进式域迁移的图像翻译方法
  7. VS转换到 COFF 期间失败 文件无效或损坏
  8. 路径取值之含正则表达式的的取值方法
  9. android重要的对象
  10. 习题4.5 顺序存储的二叉树的最近的公共祖先问题 (25 分)
  11. 萤火虫算法matlab实现,智能算法萤火虫算法Matlab源代码
  12. 机器学习读书笔记: 概率图模型
  13. vue上线后图片不显示_vue开发之图片加载不出来问题解决
  14. 长文详解材料阻燃性能试验方法
  15. 【算法】整数拆分问题
  16. C/C++输入未知组数据的方法,多行输入介绍
  17. 复旦情商课魅力女教师上课实录笔记
  18. ZYNQ 7000 AMP模式双裸核运行 双方共享内存交互
  19. ubuntu下固定IP地址
  20. Python识别中文

热门文章

  1. 程序员如何选择技术方向
  2. TINA-TI导入SPICE模型(.TSM/.LIB/.SP1)
  3. python推箱子代码详细讲解_Python使用tkinter模块实现推箱子游戏
  4. openwrt拨号上网设置
  5. codechef EBAIT Election Bait【欧几里得算法】
  6. php 红宝石,红宝石-世界名贵宝石排行榜-天天排行网
  7. 怎么把移动硬盘挂载到linux,linux 怎么挂载移动硬盘
  8. asp通用数据库连接类 access mssql mysql_asp.net 连接mssql mysql access Excel 2007数据库
  9. 城市建筑三维白膜数据的制作
  10. Daily Accumulation