prufer序列

基础知识

prufer 序列是一种 n 个节点的有标号无根树与 n2 的序列的双射关系

树转序列:每次选出编号最小的 叶节点,将其删去,并将其父亲加入序列,直到还剩两个点
线性构建:

void T_P(){
	for(int i=1;i<n;i++)fa[i]=read(),deg[fa[i]]++;
	for(int i=1,j=1;i<=n-2;i++,j++){
		while(deg[j])j++;
		p[i]=fa[j];
		while(i<=n-2&&(!(--deg[p[i]]))&&p[i]<j)p[i+1]=fa[p[i]],i++;
	}
}

序列转树:枚举最小的点,连向序列的第一个元素

void P_T(){
	for(int i=1;i<=n-2;i++)p[i]=read(),deg[p[i]]++;p[n-1]=n;
	for(int i=1,j=1;i<=n-1;i++,j++){
		while(deg[j])j++;
		fa[j]=p[i];
		while(i<n-1&&(!(--deg[p[i]]))&&p[i]<j)fa[p[i]]=p[i+1],i++;
	}
}

prufer序列的性质

  • 由于映射关系唯一,那么树的个数由序列的个数决定,于是 n 个节点的有标号无根树个数为 nn2
  • 最后剩下的两个点,一定有一个是编号最大的点
  • 考虑最后剩下的一条边一定是编号最大点向其父亲(或其最大编号的儿子)的连边,那么序列里的剩下 n2 个数恰好对应树里剩下的边
  • 一个度数为 deg 的节点其在 prufer 序列里出现 deg1

经典例题

P2290 [HNOI2004]树的计数

考虑由性质可知,对于点 i,在序列中出现 degi1
序列总长度为 n2,每个点出现 degi1 次,相当于多重集的排列,答案即为:n2degi1


CF156D Clues

设每个连通块点的个数为 si,那么如果这个连通块向外总度数为 di,那么方案数为 sidi
那么对于每个 di 序列,答案为 (k2d1,d2,...,dk)sidi
发现和多项式定理类似
于是转化为 (d1+d2+...+dk)k2si
nk2si


P5454 [THUPC2018]城市地铁规划

可以看做背包模型,将每个点看做价值为 f(degi),体积为 degi1 的物品去填充体积为 n2 的背包

背包过程中可以顺便记录转移,之后用 prufer 将序列转化成树

posted @   y_cx  阅读(88)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示