传送门

CayleyCayleyCayley公式:一个完全图有nn−2n^{n-2}nn−2棵无根生成树(可用prufer序列证明)
扩展CayleyCayleyCayley公式:被确定边分为大小为a1,a2,⋯,ama_1,a_2,\cdots, a_ma1​,a2​,⋯,am​的连通块,则有nm−2∏i=1main^{m-2}\prod\limits_{i=1}^{m}{a_i}nm−2i=1∏m​ai​种生成树

我们强制生成树中的一些边与原树中的边相同,求出生成树中至少有xxx条边于原树中边相同的方案数ansxans_xansx​,再容斥得到生成树中恰好有xxx条边与原树中边相同的方案数AnsxAns_xAnsx​。

Ansx=∑i=x(−1)i−x(ix)ansiAns_x=\sum\limits_{i=x}(-1)^{i-x}\dbinom{i}{x}ans_iAnsx​=i=x∑​(−1)i−x(xi​)ansi​

考虑一棵以uuu为根的生成子树,里面有jjj条边强制与原树中边相同。如果只加入强制相同的jjj条边,我们会得到若干连通块,即子树被非强制相同的边分成若干连通块,可以用拓展CayleyCayleyCayley公式统计方案数。

nm−2n^{m-2}nm−2可以留到最后处理,所以我们只考虑求∏i=1mai\prod\limits_{i=1}^{m}{a_i}i=1∏m​ai​,其组合意义为每个连通块内各选一个关键点的方案数。

设dp[u][j][0/1]dp[u][j][0/1]dp[u][j][0/1]表示以uuu为根的子树内有jjj条强制相同的边,uuu所在的连通块选/未选选/未选选/未选关键点选关键点方案数之和。转移如下:

若u−vu-vu−v是强制相同的边(v∈sonuv\in son_uv∈sonu​):
dp[u][j][0]×dp[v][k][0]→dp[u][j+k+1][0]dp[u][j][0]\times dp[v][k][0]\to dp[u][j+k+1][0]dp[u][j][0]×dp[v][k][0]→dp[u][j+k+1][0]
dp[u][j][0]×dp[v][k][1]+dp[u][j][1]×dp[v][k][0]→dp[u][j+k+1][1]dp[u][j][0]\times dp[v][k][1]+dp[u][j][1]\times dp[v][k][0]\to dp[u][j+k+1][1]dp[u][j][0]×dp[v][k][1]+dp[u][j][1]×dp[v][k][0]→dp[u][j+k+1][1]
若u−vu-vu−v是非强制相同的边(v∈sonuv\in son_uv∈sonu​):
dp[u][j][0]×dp[v][k][1]→dp[u][j+k][0]dp[u][j][0]\times dp[v][k][1]\to dp[u][j+k][0]dp[u][j][0]×dp[v][k][1]→dp[u][j+k][0]
dp[u][j][1]×dp[v][k][1]→dp[u][j+k][1]dp[u][j][1]\times dp[v][k][1]\to dp[u][j+k][1]dp[u][j][1]×dp[v][k][1]→dp[u][j+k][1]

类似题目:WC2019数树

#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
const int N=8010;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
int mul(int x,int y){return 1ll*x*y%mod;}
void Add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
void Dec(int &x,int y){x=x-y<0?x-y+mod:x-y;}
void Mul(int &x,int y){x=1ll*x*y%mod;}
int ksm(int a,int b){if(b<0) return ksm(ksm(a,-b),mod-2);int ans=1;while(b){if(b&1) ans=mul(ans,a);a=mul(a,a);b>>=1;}return ans;
}
int n,fac[N],ifac[N];
int cnt,head[N],nxt[N<<1],to[N<<1],siz[N];
vector<int>f[N],g[N];//f:0,g:1
void adde(int u,int v){to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}
void Clear(vector<int> &v){vector<int>().swap(v);
}
void dfs(int u,int fa){siz[u]=1;f[u].push_back(1);g[u].push_back(1);for(int i=head[u];i;i=nxt[i]){int v=to[i];if(v==fa) continue;dfs(v,u);f[u].resize(siz[u]+siz[v]);g[u].resize(siz[u]+siz[v]);for(int j=siz[u]-1;j>=0;j--){const int fu=f[u][j],gu=g[u][j];f[u][j]=g[u][j]=0;for(int k=siz[v]-1;k>=0;k--){const int fv=f[v][k],gv=g[v][k];Add(f[u][j+k+1],mul(fu,fv));Add(f[u][j+k],mul(fu,gv));Add(g[u][j+k+1],add(mul(fu,gv),mul(gu,fv)));Add(g[u][j+k],mul(gu,gv));}}siz[u]+=siz[v];Clear(f[v]),Clear(g[v]);}
}
int C(int n,int m){return mul(mul(fac[n],ifac[m]),ifac[n-m]);
}
int main(){n=read();for(int i=1;i<n;i++){int u=read(),v=read();adde(u,v),adde(v,u);}dfs(1,0);fac[0]=1;for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);ifac[n]=ksm(fac[n],mod-2);for(int i=n;i>=1;i--) ifac[i-1]=mul(ifac[i],i);for(int i=0;i<n;i++) Mul(g[1][i],ksm(n,n-i-2));for(int i=0;i<n;i++){int ans=0;for(int j=i;j<n;j++){if((j-i)&1) Dec(ans,mul(C(j,i),g[1][j]));else Add(ans,mul(C(j,i),g[1][j]));}printf("%d ",ans);}return 0;
}

[XXSY] 构树(prufer序列,树上连通块DP)相关推荐

  1. 树形dp ---- gym101655 D - Delta Quadrant 树上连通块思维换根 + 树形dp

    题目链接 题目大意: 给你一颗NNN个节点的树,树上每条边有边权就是遍历的时间,你可以从任意节点出发遍历N−kN-kN−k个点并且回到出发点,问你最短的时间是多少? k∈[0,min(N,20)],N ...

  2. 2021牛客暑期多校训练营4 D-Rebuild Tree(prufer序列+树形dp)

    D-Rebuild Tree Prufer 是这样建立的:每次选择一个编号最小的叶结点并删掉它,然后在序列中记录下它连接到的那个结点.重复n−2n-2n−2次后就只剩下两个结点,算法结束.(为什么不是 ...

  3. 【XSY2519】神经元 prufer序列 DP

    题目描述 有\(n\)点,每个点有度数限制,\(\forall i(1\leq i\leq n)\),让你选出\(i\)个点,再构造一棵生成树,要求每个点的度数不超过度数限制.问你有多少种方案. \( ...

  4. 树上连通有关背包:【BZOJ4182】shopping 【HDU6566】The Hanged Man

    选这两道题是因为这两道题都是树上背包,而且选的点的要求都与连通性有关,而且都是按 dfs 序 DP 来模拟不断加入物品,而且都能用树剖和点分治优化(不过优化的点一个跟子树大小有关一个跟深度有关),比较 ...

  5. 解题报告(八) prufer 序列与 Cayley 公式(ACM / OI)超高质量题解

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  6. [C] [编程题]连通块(DFS解决)

    时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 256M,其他语言512M 来源:牛客网 金山办公2020校招服务端开发工程师笔试题(一) 题目描述 给一个01矩阵,1代表是陆地,0代表 ...

  7. 曼哈顿距离与切比雪夫距离的转化及prufer序列

    目录 曼哈顿距离与切比雪夫距离的相互转化 prufer序列 1. 曼哈顿距离 与 切比雪夫距离 的相互转化 曼哈顿距离 |x1−x2|+|y1−y2|=max(x1−x2+y1−y2,x1−x2−y1 ...

  8. Prufer序列 生成树定理

    Description 在图论中,树的定义是连通且无环的无向图.对于一棵有 nn 个节点且节点从 11 到 nn 编号的树,它的 Prufer 序列是一个唯一的长为 n−2n−2 的标号序列. Pru ...

  9. DFS序+线段树 hihoCoder 1381 Little Y's Tree(树的连通块的直径和)

    题目链接 #1381 : Little Y's Tree 时间限制:24000ms 单点时限:4000ms 内存限制:512MB 描述 小Y有一棵n个节点的树,每条边都有正的边权. 小J有q个询问,每 ...

最新文章

  1. vim常用命令总结 (转)
  2. OpenCMS integration with Spring MVC--reference
  3. 英伟达显卡不同架构_英伟达新款笔记本显卡全阵容曝光:共计六款
  4. 虚拟内存的作用、分页系统实现虚拟内存原理
  5. MFC根据颜色数组自定义位图并显示到窗口
  6. python和lisp学哪个好_五位专家跟你讲讲为啥Python更适合做AI/机器学习
  7. 2143亿!2018年天猫“双11”成交总额是这样预测的
  8. 解决“‘pip‘ 不是内部或外部命令,也不是可运行的程序或批处理文件“的问题
  9. 利用Matlab绘制图像中的某一行或者某一列的灰度曲线
  10. app小窗口悬浮工具_悬浮窗口大师
  11. 计算机视觉引论及数字成像系统
  12. pyqt5 加载gif_PyQt5:在Qmovi中重新加载gif
  13. Dell服务器误删阵列恢复操作
  14. 时域,空域,频域的基本概念
  15. NavigationDuplicated: Avoided redundant navigation to current location: 解决办法
  16. jetson-nano编译qt5.15.2带opengl,xcb
  17. memcmp的性能分析
  18. MySQL ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
  19. 2021新手找货源技巧来啦!萌啦货源手把手教你选品!
  20. Ubuntu个人笔记

热门文章

  1. [JavaWeb-JavaScript]JavaScript运算符
  2. [蓝桥杯2016初赛]平方怪圈-数论,模拟
  3. Divide and Sum CodeForces - 1445D(排列组合+逆元)
  4. python车辆识别硬件_Opencv python之车辆识别项目
  5. 找出一个字符串中出现次数最多的字_Day34:第一个只出现一次的字符
  6. P3911 最小公倍数之和 (atcoder C - LCMs)(反演)
  7. 2018-2019 ACM-ICPC, Asia Shenyang Regional Contest E. The Kouga Ninja Scrolls 切比雪夫距离 +线段树
  8. Educational Codeforces Round 80 (Rated for Div. 2) C. Two Arrays 组合数|dp
  9. Educational Codeforces Round 106 (Rated for Div. 2) D. The Number of Pairs 数论gcd
  10. Codeforces Round #703 (Div. 2) D . Max Median 二分 +思维