浅谈Prufer序列
\(\text{Prufer}\)序列,是树与序列的一种双射。
构建过程:
每次找到一个编号最小的叶子节点\(Leaf\),将它删掉,并将它所连接的点的度数\(-1\),且加入\(\text{Prufer}\)序列。
重复上述步骤,直到只剩下两个点。
实现:
考虑如何实现。
最朴素的显然每次暴力找,复杂度\(O(n^2).\)显然不够优秀。
用堆来维护节点,显然可以做到\(O(n\log n).\)
考虑线性实现:维护一个指针,每次指向编号最小的叶节点。删除之后,如果新产生了叶节点并且编号要比指针编号小,则加入\(\text{Prufer}\)序列,继续删除。否则自增到下一个叶节点。
指针只会增加,最多增加\(O(n)次\),时间复杂度即为\(O(n).\)
Rebuild重建
若已知\(\text{Prufer}\)序列,如何重建树?
先通过\(\text{Prufer}\)序列将每一个元素的度\((\text{Deg})\)还原。
同样地,维护一个指针,每次指向编号最小的叶子节点,并把它与当前\(\text{Prufer}\)序列的第一个元素相连。将两个元素的度都减一,并继续找新产生的\(Leaf\),同\(\text{Prufer}\)序列的构建过程。
时间复杂度同样是\(O(n).\)
用处:
- 凯莱定理:\(n\)个点的完全图生成树个数为\(n^{n-2}.\)
- 用来造树的数据
- 推一堆计数式子
例题
- 模板 Link
代码实现:
下面是模板代码,用了\(\text{fread.}\)
#include<bits/stdc++.h>
using namespace std;
int n,m,f[5000010],p[5000010],d[5000010];
long long ans;
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read(){
int s=0,w=1;
char ch=gc();
while(!isdigit(ch)){
if(ch=='-')w=-1;
ch=gc();
}
while(isdigit(ch)){
s=s*10+ch-'0';
ch=gc();
}
return w==-1?-s:s;
}
}
using namespace IO;
inline void Turn_Prufer(){
for(int i=1;i<n;++i)f[i]=read(),++d[f[i]];
//j为指针
for(int i=1,j=1;i<n-1;++i,++j){
while(d[j])++j;p[i]=f[j];//找到第一个deg为0的点,即为叶子,删掉,把它相连的点加到Prufer里
while(i<n-1&&!--d[p[i]]&&p[i]<j)p[i+1]=f[p[i]],++i;//如果Prufer还没找完,并且删掉它爹(这里新产生的点就是p[i])的度数后也成为叶子,且它的编号要小,此处的p[i]就是上一个点(j)的爹
}
for(int i=1;i<n-1;++i)ans^=1ll*i*p[i];
}
inline void Turn_Father(){
for(int i=1;i<n-1;++i)p[i]=read(),++d[p[i]];
p[n-1]=n;
for(int i=1,j=1;i<n;++i,++j){
while(d[j])++j;f[j]=p[i];
while(i<n&&!--d[p[i]]&&p[i]<j)f[p[i]]=p[i+1],++i;//p[i]就是新产生的点,根据Prufer逆向构造即可
}
for(int i=1;i<n;++i)ans^=1ll*i*f[i];
}
inline void write(long long A){
if(A<0)putchar('-'),A=-A;
if(A>9)write(A/10);
putchar(A%10+'0');
}
int main(){
n=read(),m=read();
if(m==1)Turn_Prufer();
else Turn_Father();
write(ans);
return 0;
}
浅谈Prufer序列的更多相关文章
- 浅谈WebService的版本兼容性设计
在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...
- Linux特殊符号浅谈
Linux特殊字符浅谈 我们经常跟键盘上面那些特殊符号比如(?.!.~...)打交道,其实在Linux有其独特的含义,大致可以分为三类:Linux特殊符号.通配符.正则表达式. Linux特殊符号又可 ...
- 浅谈Oracle事务【转载竹沥半夏】
浅谈Oracle事务[转载竹沥半夏] 所谓事务,他是一个操作序列,这些操作要么都执行,要么都不执行,是一个不可分割的工作单元.通俗解释就是事务是把很多事情当成一件事情来完成,也就是大家都在一条船上,要 ...
- 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...
- [转]浅谈https\ssl\数字证书
浅谈https\ssl\数字证书 http://www.cnblogs.com/P_Chou/archive/2010/12/27/https-ssl-certification.html 全球可信的 ...
- 浅谈c#枚举
结构中的成员可以赋值,枚举呢....是取值,只读的 以下情况可以考虑将类创建为结构:(1)如果一个类其中的字段非常少,所有字段占用的内存总量不超过8.16字节:(2)如果一个类中的字段都是值类型: 关 ...
- C++ STL中的常用容器浅谈
STL是C/C++开发中一个非常重要的模板,而其中定义的各种容器也是非常方便我们大家使用.下面,我们就浅谈某些常用的容器.这里我们不涉及容器的基本操作之类,只是要讨论一下各个容器其各自的特点.STL中 ...
- 浅谈Base64编码
浅谈Base64编码 我打赌当你见到Base64这个词的时候你会觉得在哪里见过,因为在你能够上网看到这篇文章的时候你已经在后台使用它了.如果您对二进制数有所了解,你就可以开始读它了. 打开一封Emai ...
- 浅谈 Java 主流开源类库解析 XML
在大型项目编码推进中,涉及到 XML 解析问题时,大多数程序员都不太会选用底层的解析方式直接编码. 主要存在编码复杂性.难扩展.难复用....,但如果你是 super 程序员或是一个人的项目,也不妨一 ...
随机推荐
- C# OWC11
public void OcwChart(int[] Data,string[] DataName,string Yname,string Xname,string ChartName,string ...
- C# Chart各个属性详细解析、应用
Chart笔记 前台页面代码: <form id="form1" runat="server"> <div> <asp:Chart ...
- P3311 [SDOI2014]数数 AC自动机+数位DP
题意 给定一个正整数N和n个模式串,问不大于N的数字中有多少个不包含任意模式串,输出对\(1e^9+7\)取模后的答案. 解题思路 把所有模式串都加入AC自动机,然后跑数位DP就好了.需要注意的是,这 ...
- Mybatis联合查询(一)
Mybatis的简单联合查询操作: 实体类: Employee: package com.test.mybatis; public class Employee { private Integer i ...
- el-select 封装
这里打算封装一个全局el-select组件 MySelect.vue <template> <el-select v-if="options.length!==0" ...
- 2020年1月31日 安装Python的requests包记录
C:\Users\ufo>pip install requests Collecting requests WARNING: Retrying (Retry(total=, connect=No ...
- logback1.11的一个bug:有线程持续不断写入log文件,log文件就不会按设定以日期切换。
此Bug的解决方案请见:https://www.cnblogs.com/xiandedanteng/p/12205422.html logback是log4j的后继者,作者也是同一人,但其中的bug不 ...
- java安全编码指南之:Number操作
目录 简介 Number的范围 区分位运算和算数运算 注意不要使用0作为除数 兼容C++的无符号整数类型 NAN和INFINITY 不要使用float或者double作为循环的计数器 BigDecim ...
- HTML-CSS-JS Prettify 代码格式化插件
前提:已经安装 node.js.安装插件 HTML-CSS-JS Prettify,修改node路径,即可通过单击右键 HTML-CSS-JS Prettify 中的 Prettify Code 使用 ...
- RabbitMQ和Kafka的高可用集群原理
前言 小伙伴们,通过前边文章的阅读,相信大家已经对RocketMQ的基本原理有了一个比较深入的了解,那么大家对当前比较常用的RabbitMQ和Kafka是不是也有兴趣了解一些呢,了解的多一些也不是坏事 ...