【CF917D】Stranger Trees 树形DP+Prufer序列
【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的总贡献。最后容斥一发即可。
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- using namespace std;
- typedef long long ll;
- const ll P=1000000007;
- int n,m,cnt;
- int to[210],nxt[210],head[110],siz[110];
- ll f[110][110][110],g[110][110],c[110][110],h[110],bt[110];
- inline int rd()
- {
- int ret=0,f=1; char gc=getchar();
- while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
- while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
- return ret*f;
- }
- void dfs(int x,int fa)
- {
- f[x][1][0]=1,siz[x]=1;
- for(int i=head[x],j,k,a,b,y;i!=-1;i=nxt[i]) if(to[i]!=fa)
- {
- y=to[i],dfs(to[i],x);
- memset(g,0,sizeof(g));
- for(j=1;j<=siz[x];j++) for(k=1;k<=siz[y];k++)
- {
- for(a=0;a<siz[x];a++) for(b=0;b<siz[y];b++)
- {
- g[j+k][a+b+1]=(g[j+k][a+b+1]+f[x][j][a]*f[y][k][b])%P;
- g[j][a+b]=(g[j][a+b]+f[x][j][a]*f[y][k][b]%P*k)%P;
- }
- }
- memcpy(f[x],g,sizeof(g));
- siz[x]+=siz[y];
- }
- }
- inline void add(int a,int b)
- {
- to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++;
- }
- int main()
- {
- n=rd();
- int i,j,a,b;
- memset(head,-1,sizeof(head));
- for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
- dfs(1,0);
- for(bt[0]=i=1;i<=n;i++) bt[i]=bt[i-1]*n%P;
- 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;
- for(i=1;i<n;i++) for(j=0;j<n;j++) h[j]=(h[j]+f[1][i][j]*i)%P;
- h[n-1]=1;
- for(i=0;i<n-1;i++) h[i]=h[i]*bt[n-i-2]%P;
- for(i=n-1;i>=0;i--)
- {
- for(j=i+1;j<n;j++) h[i]=(h[i]-c[j][i]*h[j])%P;
- h[i]=(h[i]+P)%P;
- }
- for(i=0;i<n;i++) printf("%lld ",h[i]);
- return 0;
- }
【CF917D】Stranger Trees 树形DP+Prufer序列的更多相关文章
- CF917D Stranger Trees
CF917D Stranger Trees 题目描述 给定一个树,对于每个\(k=0,1\cdots n-1\),问有多少个生成树与给定树有\(k\)条边重合. 矩阵树定理+高斯消元 我们答案为\(f ...
- hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治的话,每次要做一次树形DP:但时间应该是 siz*m2 的.可以用 FWT 变成 siz*ml ...
- HDU 5629 Clarke and tree dp+prufer序列
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=562 题意: 求给每个节点的度数允许的最大值,让你求k个节点能组成的不同的生成树个数. 题解: 对于n ...
- CF917D. Stranger Trees & TopCoder13369. TreeDistance(变元矩阵树定理+高斯消元)
题目链接 CF917D:https://codeforces.com/problemset/problem/917/D TopCoder13369:https://community.topcoder ...
- 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 ...
- CF917D Stranger Trees【矩阵树定理,高斯消元】
题目链接:洛谷 题目大意:给定一个$n$个节点的树$T$,令$ans_k=\sum_{T'}[|T\cap T'|=k]$,即有$k$条边重合.输出$ans_0,ans_1,\ldots,ans_{n ...
- [CF917D]Stranger Trees[矩阵树定理+解线性方程组]
题意 给你 \(n\) 个点的无向完全图,指定一棵树 \(S\),问有多少棵生成树和这棵树的公共边数量为 \(k\in[0,n-1]\) \(n\leq 100\) 分析 考虑矩阵树定理,把对应的树边 ...
- HDU 4123 (2011 Asia FZU contest)(树形DP + 维护最长子序列)(bfs + 尺取法)
题意:告诉一张带权图,不存在环,存下每个点能够到的最大的距离,就是一个长度为n的序列,然后求出最大值-最小值不大于Q的最长子序列的长度. 做法1:两步,第一步是根据图计算出这个序列,大姐头用了树形DP ...
- 5.13 省选模拟赛 优雅的绽放吧,墨染樱花 多项式 prufer序列 计数 dp
LINK:优雅的绽放吧,墨染樱花 当时考完只会50分的做法 最近做了某道题受到启发 故会做这道题目了.(末尾附30分 50分 100分code 看到度数容易想到prufer序列 考虑dp统计方案数. ...
随机推荐
- iview 下拉刷新loadTop报错解决
<div class="noData" v-if="lifeList.length==0"> <img src="../assets ...
- 找不到 android-support-v4 解决办法
Project->properties->Java Build Path->Libraries->Add External Jars中加入sdk目录下的extras/andro ...
- Google语音识别API 使用方法
官方位置:https://cloud.google.com/speech/
- Ruby 面向对象知识详解
Ruby 是纯面向对象的语言,Ruby 中的一切都是以对象的形式出现.Ruby 中的每个值都是一个对象,即使是最原始的东西:字符串.数字,甚至连 true 和 false 都是对象.类本身也是一个对象 ...
- git 使gitnore立即生效
由于之前有些需要过滤的文件已经提交到版本库了,之后再想起来添加时候已经晚了,使用如下方法 Git忽略规则和.gitignore规则不生效的解决办法 Git忽略规则: 在git中如果想忽略掉某个文件 ...
- selenium +chrome headless Adhoc模式渲染网页
mannual和adhoc模式比较 Manual vs. Adhoc In the script above, we start the ChromeDriver server process whe ...
- SpringBoot------热部署(Springloaded)
为啥要热部署: 在修改代码的时候,不需要重新启动程序,程序会自动进行编译 注意: 控制器中新增加的方法是不能进行热部署的 方法: 1.在pom.xml文件里面添加下面代码 <project> ...
- MySQL用户认证及权限控制
一.MySQL用户认证: 登录并不属于访问控制机制,而属于用户身份识别和认证: 1.用户名—user 2.密码—password 3.登录mysqld主机—host 实现用户登录MySQL,建立连接. ...
- pycharm 激活
方法1: (1)更新**hosts**文件 [hosts文件百度云下载地址](https://pan.baidu.com/s/1o9ZujxS) **hosts**文件在windows中的地址为: C ...
- 【安全开发】PHP安全编码规范
申明:本文非笔者原创,原文转载自:https://github.com/SecurityPaper/SecurityPaper-web/blob/master/_posts/2.SDL%E8%A7%8 ...