prufer序列

prufer序列是一种树形结构和数列相互映射的规则

1|0与其他序列的区别

dfs序,将一棵子树映射为一段连续的区间
二叉搜索树,中序遍历是单调不减的序列
prufer序列:

  • 1.是一个和树的双射,唯一对应一棵树
  • 2.包含结点的度数和连接关系

2|0使用场景

将构造树转化为构造序列,将统计树转化为统计序列,将树的dp转化为数列的dp

3|0如何得到prufer序列

  • 1.统计树上所有结点的度数degree[i]
  • 2.找到所有度数为1的结点中编号最小的那个结点cur
  • 3.令p[i]=fa[cur],同时将degree[fa[cur]]--
  • 4.重复步骤2-3,直到剩余两个点时结束

4|0性质

  • 1.结点x在prufer序列中出现的次数+1就是degree[x]
  • 2.编号最大的点n绝对是剩下的2个结点之一

因此一般把n当作根节点,这样不会删掉根节点

5|0P6086 【模板】Prufer 序列

#include<bits/stdc++.h> #define int long long using namespace std; int pre[5000010]; int fa[5000010]; int deg[5000010]; int n,m; int ans; void prufer(){ int cur;//fa为父亲序列 for(int i=1;i<=n;i++){ if(deg[i]==1){ cur=i;//最小的度数为1的点 break; } } int leaf=cur; for(int i=1;i<=n-2;i++){ //cout<<leaf<<endl; ans=ans^(i*fa[leaf]); deg[fa[leaf]]--; if(deg[fa[leaf]]==1 && fa[leaf]<cur){ leaf=fa[leaf]; continue; } else{ cur++; while(deg[cur]!=1){ cur++; } leaf=cur; } } cout<<ans; } void pre_tree(){ for(int i=1;i<=n;i++) deg[i]=1; int cur,leaf; for(int i=1;i<=n-2;i++) deg[pre[i]]++; for(int i=1;i<=n;i++){ if(deg[i]==1){ cur=i; break; } } leaf=cur; for(int i=1;i<=n-2;i++){ int f=fa[leaf]=pre[i]; deg[f]--; if(deg[f]==1 && f<cur){ leaf=f; continue; } else{ cur++; while(deg[cur]!=1){ cur++; } leaf=cur; } } fa[leaf]=n; for(int i=1;i<n;i++) ans=ans^(fa[i]*i); cout<<ans; } signed main(){ cin>>n>>m; if(m==1){ for(int i=1;i<n;i++){ cin>>fa[i]; deg[i]++; deg[fa[i]]++; } //for(int i=1;i<=n;i++) cout<<deg[i]<<endl; prufer(); } else{ for(int i=1;i<n-1;i++){ cin>>pre[i]; } pre_tree(); } return 0; }

6|0P5454 [THUPC2018] 城市地铁规划

观察题目的便利度计算公式,发现这个东西显然是可以预处理的,而f(x)的参数x显然是点x的度数。

题目中说:
新建的地铁轨道尽可能少,但任意两座地标之间都需要能通过地铁相互到达。
其实就是一棵树,那么度数总和就是2n-2,于是可以对于度数完全背包(注意每一个点都必须有度数),并且在做完全背包的过程中记录上一个状态,以便得到每一个点的度数。

得到度数用prufer构造成树就行了(其他复杂度更高的方法也是可以的,瓶颈在完全背包);

7|0常用性质

  • 1.对于n个点的完全图,其生成树的方案数为\(n^{n-2}\)
  • 2.对于n个点的无根树,其树的方案数为\(n^{n-2}\)
  • 3.对于n个点的有根树,其树的方案数为\(n^{n-1}\)
    前面三个都挺显然的
  • 4.对于n个节点,约定点i的度数为d[i],满足条件的树的方案数为\(\frac{(n-2)!}{\prod_{i=1}^{n}(d_i-1)!}\)

8|0P2624 [HNOI2008] 明明的烦恼

从prufer序列的角度:
设有x个点确定了度数d[i],还剩n-x个点待确定
还有n-2-x个数需要出现,在n-x个点中选取


__EOF__

本文作者星河倒注
本文链接https://www.cnblogs.com/wangwenhan/p/18025188.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   星河倒注  阅读(68)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示