prufer序列
基础知识
序列是一种 个节点的有标号无根树与 的序列的双射关系
树转序列:每次选出编号最小的 叶节点,将其删去,并将其父亲加入序列,直到还剩两个点
线性构建:
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序列的性质
- 由于映射关系唯一,那么树的个数由序列的个数决定,于是 个节点的有标号无根树个数为
- 最后剩下的两个点,一定有一个是编号最大的点
- 考虑最后剩下的一条边一定是编号最大点向其父亲(或其最大编号的儿子)的连边,那么序列里的剩下 个数恰好对应树里剩下的边
- 一个度数为 的节点其在 序列里出现 次
经典例题
考虑由性质可知,对于点 ,在序列中出现 次
序列总长度为 ,每个点出现 次,相当于多重集的排列,答案即为:
设每个连通块点的个数为 ,那么如果这个连通块向外总度数为 ,那么方案数为
那么对于每个 序列,答案为
发现和多项式定理类似
于是转化为
即
可以看做背包模型,将每个点看做价值为 ,体积为 的物品去填充体积为 的背包
背包过程中可以顺便记录转移,之后用 将序列转化成树
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效