Prufer 序列
1.Prufer是干啥的
把一个无根树变成一个序列,也可以把一个序列变成一个序列
2.性质
-
1.prufer序列与无根树一一对应
-
2.度数为 的结点会在 序列中出现 次。
-
3.一个 个结点的无向完全图的生成树的个数 (Cayley公式)。
3.转化过程
把无根树变成序列
6
/
5
/ \
4 2
/
3
/
1
每次看度数=1的叶子节点中删除后总数变化最小的点
删去1变化最小,输出删除1前1的父节点3
6
/
5
/ \
4 2
/
3
删去2变化最小,输出删除2前2的父节点5
6
/
5
/
4
/
3
删去3变化最小,输出4
6
/
5
/
4
删去4变化最小,输出5
6
/
5
剩下两个点后,一定删除非最大的数,最后剩下的一个点一定是输出最大的n号点 6
6
/
5
4.原理
从小到大枚举 (编号最小的度数的叶子节点),把 删掉后最多产生一个新的叶子节点
-
情况1:删叶子节点后,新多出来的点k比j大,不用管,j会从小到大枚举,迟早会枚举到这个点k
-
情况2:删叶子节点后,新多出来的点比j小,说明k就是当前最小叶子节点
代码实现
#include<bits/stdc++.h>
#define int long long
#define rint register int
#define endl '\n'
using namespace std;
const int N = 5e6 + 5;
int n,m,f[N],d[N],p[N];
int inline tree2prufer(){
for(rint i=1;i<n;i++) cin>>f[i],d[f[i]]++;
for(rint i=1,j=1;i<n-1;j++){
while(d[j]){
j++;
}
p[i++]=f[j];
while(i<n-1&&--d[p[i-1]]==0&&p[i-1]<j){
p[i++]=f[p[i-1]];
}
}
int ans=0;
for(rint i=1;i<n-1;i++)
ans=ans^(1ll*i*p[i]);
return ans;
}
int inline prufer2tree(){
for(rint i=1;i<=n-2;i++) cin>>p[i],d[p[i]]++;
p[n-1]=n;
for(rint i=1,j=1;i<n;i++,j++){
while(d[j]){
j++;
}
f[j]=p[i];
while(i<n-1&&--d[p[i]]==0&&p[i]<j){
f[p[i]]=p[i+1];
i++;
}
}
int ans=0;
for(rint i=1;i<=n-1;i++)
ans=ans^(1ll*i*f[i]);
return ans;
}
signed main(){
cin>>n>>m;
int res;
if(m==1)
res=tree2prufer();
else
res=prufer2tree();
cout<<res<<endl;
return 0;
}
本文作者:PassName
本文链接:https://www.cnblogs.com/spaceswalker/p/16480323.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步