【CF917D】Stranger Trees

题意:给你一棵n个点的树,对于k=1...n,问你有多少有标号的n个点的树,与给出的树有恰好k条边相同?

$n\le 100$

题解:我们先考虑容斥,求出和给出的树至少有k个点相同的树的数量。我们先选出原树中的k条边,然后剩下的边随便连。选出k条边后,原树被分成n-k个连通块,设其大小分别为$siz_1,siz_2...siz_{n-k}$。那么剩下的边随便连的方案数是多少呢?我们不妨把每个连通块看成一个点,答案变成n个点的完全图的生成树个数,根据Prufer序列知道这个答案是$n^{n-2}$。但是这里一个连通块的大小并不是1。对于一个大小为$siz$的连通块,如果它在Prufer序列中出现了j次,那么它对答案的贡献其实是$siz^{j+1}$(因为它的度数是j+1)。我们可以先把$\prod\limits_{i=1}^{n-k}siz_i$提出来,然后对于Prufer序列中的每个位置,如果它是第i个连通块,则贡献为$siz_i$,所以总的贡献为$\sum\limits_{i=1}^{n-k}siz_i=n$,那么答案就是$\prod\limits_{i=1}^{n-k}siz_i\times n^{n-k-2}$。

所以我们考虑树形DP,用f[x][a][b]表示在x的子树中,已经连了a条边,包含x的连通块大小为b的总贡献。最后容斥一发即可。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. using namespace std;
  5. typedef long long ll;
  6. const ll P=1000000007;
  7. int n,m,cnt;
  8. int to[210],nxt[210],head[110],siz[110];
  9. ll f[110][110][110],g[110][110],c[110][110],h[110],bt[110];
  10. inline int rd()
  11. {
  12. int ret=0,f=1; char gc=getchar();
  13. while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
  14. while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
  15. return ret*f;
  16. }
  17. void dfs(int x,int fa)
  18. {
  19. f[x][1][0]=1,siz[x]=1;
  20. for(int i=head[x],j,k,a,b,y;i!=-1;i=nxt[i]) if(to[i]!=fa)
  21. {
  22. y=to[i],dfs(to[i],x);
  23. memset(g,0,sizeof(g));
  24. for(j=1;j<=siz[x];j++) for(k=1;k<=siz[y];k++)
  25. {
  26. for(a=0;a<siz[x];a++) for(b=0;b<siz[y];b++)
  27. {
  28. g[j+k][a+b+1]=(g[j+k][a+b+1]+f[x][j][a]*f[y][k][b])%P;
  29. g[j][a+b]=(g[j][a+b]+f[x][j][a]*f[y][k][b]%P*k)%P;
  30. }
  31. }
  32. memcpy(f[x],g,sizeof(g));
  33. siz[x]+=siz[y];
  34. }
  35. }
  36. inline void add(int a,int b)
  37. {
  38. to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++;
  39. }
  40. int main()
  41. {
  42. n=rd();
  43. int i,j,a,b;
  44. memset(head,-1,sizeof(head));
  45. for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
  46. dfs(1,0);
  47. for(bt[0]=i=1;i<=n;i++) bt[i]=bt[i-1]*n%P;
  48. for(i=0;i<=n;i++) for(c[i][0]=j=1;j<=i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%P;
  49. for(i=1;i<n;i++) for(j=0;j<n;j++) h[j]=(h[j]+f[1][i][j]*i)%P;
  50. h[n-1]=1;
  51. for(i=0;i<n-1;i++) h[i]=h[i]*bt[n-i-2]%P;
  52. for(i=n-1;i>=0;i--)
  53. {
  54. for(j=i+1;j<n;j++) h[i]=(h[i]-c[j][i]*h[j])%P;
  55. h[i]=(h[i]+P)%P;
  56. }
  57. for(i=0;i<n;i++) printf("%lld ",h[i]);
  58. return 0;
  59. }

【CF917D】Stranger Trees 树形DP+Prufer序列的更多相关文章

  1. CF917D Stranger Trees

    CF917D Stranger Trees 题目描述 给定一个树,对于每个\(k=0,1\cdots n-1\),问有多少个生成树与给定树有\(k\)条边重合. 矩阵树定理+高斯消元 我们答案为\(f ...

  2. hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治的话,每次要做一次树形DP:但时间应该是 siz*m2 的.可以用 FWT 变成 siz*ml ...

  3. HDU 5629 Clarke and tree dp+prufer序列

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=562 题意: 求给每个节点的度数允许的最大值,让你求k个节点能组成的不同的生成树个数. 题解: 对于n ...

  4. CF917D. Stranger Trees & TopCoder13369. TreeDistance(变元矩阵树定理+高斯消元)

    题目链接 CF917D:https://codeforces.com/problemset/problem/917/D TopCoder13369:https://community.topcoder ...

  5. Regionals 2014 >> Asia - Taichung 7003 - A Balance Game on Trees 树形DP + 二维费用背包

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  6. CF917D Stranger Trees【矩阵树定理,高斯消元】

    题目链接:洛谷 题目大意:给定一个$n$个节点的树$T$,令$ans_k=\sum_{T'}[|T\cap T'|=k]$,即有$k$条边重合.输出$ans_0,ans_1,\ldots,ans_{n ...

  7. [CF917D]Stranger Trees[矩阵树定理+解线性方程组]

    题意 给你 \(n\) 个点的无向完全图,指定一棵树 \(S\),问有多少棵生成树和这棵树的公共边数量为 \(k\in[0,n-1]\) \(n\leq 100\) 分析 考虑矩阵树定理,把对应的树边 ...

  8. HDU 4123 (2011 Asia FZU contest)(树形DP + 维护最长子序列)(bfs + 尺取法)

    题意:告诉一张带权图,不存在环,存下每个点能够到的最大的距离,就是一个长度为n的序列,然后求出最大值-最小值不大于Q的最长子序列的长度. 做法1:两步,第一步是根据图计算出这个序列,大姐头用了树形DP ...

  9. 5.13 省选模拟赛 优雅的绽放吧,墨染樱花 多项式 prufer序列 计数 dp

    LINK:优雅的绽放吧,墨染樱花 当时考完只会50分的做法 最近做了某道题受到启发 故会做这道题目了.(末尾附30分 50分 100分code 看到度数容易想到prufer序列 考虑dp统计方案数. ...

随机推荐

  1. iview 下拉刷新loadTop报错解决

    <div class="noData" v-if="lifeList.length==0"> <img src="../assets ...

  2. 找不到 android-support-v4 解决办法

    Project->properties->Java Build Path->Libraries->Add External Jars中加入sdk目录下的extras/andro ...

  3. Google语音识别API 使用方法

    官方位置:https://cloud.google.com/speech/

  4. Ruby 面向对象知识详解

    Ruby 是纯面向对象的语言,Ruby 中的一切都是以对象的形式出现.Ruby 中的每个值都是一个对象,即使是最原始的东西:字符串.数字,甚至连 true 和 false 都是对象.类本身也是一个对象 ...

  5. git 使gitnore立即生效

    由于之前有些需要过滤的文件已经提交到版本库了,之后再想起来添加时候已经晚了,使用如下方法 Git忽略规则和.gitignore规则不生效的解决办法   Git忽略规则: 在git中如果想忽略掉某个文件 ...

  6. selenium +chrome headless Adhoc模式渲染网页

    mannual和adhoc模式比较 Manual vs. Adhoc In the script above, we start the ChromeDriver server process whe ...

  7. SpringBoot------热部署(Springloaded)

    为啥要热部署: 在修改代码的时候,不需要重新启动程序,程序会自动进行编译 注意: 控制器中新增加的方法是不能进行热部署的 方法: 1.在pom.xml文件里面添加下面代码 <project> ...

  8. MySQL用户认证及权限控制

    一.MySQL用户认证: 登录并不属于访问控制机制,而属于用户身份识别和认证: 1.用户名—user 2.密码—password 3.登录mysqld主机—host 实现用户登录MySQL,建立连接. ...

  9. pycharm 激活

    方法1: (1)更新**hosts**文件 [hosts文件百度云下载地址](https://pan.baidu.com/s/1o9ZujxS) **hosts**文件在windows中的地址为: C ...

  10. 【安全开发】PHP安全编码规范

    申明:本文非笔者原创,原文转载自:https://github.com/SecurityPaper/SecurityPaper-web/blob/master/_posts/2.SDL%E8%A7%8 ...