prufer序列

news/2024/7/7 20:15:01/文章来源:https://www.cnblogs.com/hzoi-Cu/p/18284130

prufer序列

  • 用途: 将带标号的树用唯一的整数序列表示出来,证明凯莱公式。

  • 构造方法:每次选择一个编号最小的叶结点并删掉它,然后在序列中记录下它连接到的那个结点。重复\(n-2\)次后就只剩下两个结点,算法结束。

    举个栗子(本图来自baoziwu2,侵删)

    image

    显然可以有一个用堆做的方法,时间复杂度\(O(n\log n)\)

    \(code:\)

    点此查看代码
    #include<bits/stdc++.h>
    #include<bits/extc++.h>
    // using namespace __gnu_pbds;
    // using namespace __gnu_cxx;
    using namespace std;
    #define infile(x) freopen(x,"r",stdin)
    #define outfile(x) freopen(x,"w",stdout)
    #define errfile(x) freopen(x,"w",stderr)
    using ll=long long;using ull=unsigned long long;
    char *p1,*p2,buf[1<<20];
    #define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
    #ifdef linux
    #define pc putchar_unlocked
    #else
    #define pc putchar
    #endif
    namespace IO{template<typename T>inline bool read(T &x){x=0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x<<1)+(x<<3)+(s^48);if(!f) x=~x+1;return true;}inline bool read(double &x){x=0.0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x*10)+(s^48);if(s!='.'){return true;}double res=0.1;s=gc();for(;'0'<=s&&s<='9';res/=10,s=gc()) x+=(s^48)*res;x=f?x:-x;return true;}inline bool read(long double &x){x=0.0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x*10)+(s^48);if(s!='.'){return true;}double res=0.1;s=gc();for(;'0'<=s&&s<='9';res/=10,s=gc()) x+=(s^48)*res;x=f?x:-x;return true;}inline bool read(float &x){x=0.0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x*10)+(s^48);if(s!='.'){return true;}double res=0.1;s=gc();for(;'0'<=s&&s<='9';res/=10,s=gc()) x+=(s^48)*res;x=f?x:-x;return true;}inline bool read(string &str){string ().swap(str);char s=gc();for(;s==' '||s=='\n';s=gc());if(s==EOF) return false; for(;s!=' '&&s!='\n'&&s!=EOF;s=gc())str.push_back(s);return true;}inline bool read_line(string &str){string ().swap(str);char s=gc();for(;s==' '||s=='\n';s=gc());if(s==EOF) return false;for(;s!='\n'&&s!=EOF;s=gc()){str.push_back(s);}return true;}inline bool read_line(char *str){int len=0;char s=gc();for(;s==' '||s=='\n';s=gc());if(s==EOF) return false;for(;s!='\n'&&s!=EOF;s=gc()){str[len]=s;len++;}str[len]='\0';return true;}inline bool read(char &s){char x=gc();for(;x==' '||x=='\n';x=gc());if(x==EOF||x==' '||x=='\n')return false;s=x;return true;}inline bool read(char *s){int len=0;char x=gc();for(;x==' '||x=='\n';x=gc());if(x==EOF)return false;for(;x!=' '&&x!='\n'&&x!=EOF;x=gc())s[len++]=x;s[len]='\0';return true;}template<class T,class... Args> inline bool read(T &x,Args&... args){return (read(x)&&read(args...));}template<class T>inline void write(T x){static T st[45];int top=0;if(x<0)x=~x+1,pc('-');do{st[top++]=x%10;}while(x/=10);while(top)pc(st[--top]^48);}inline void write(char x){pc(x);}inline void write(string s){for(int i=0;s[i];++i) pc(s[i]);}inline void write(char *s){int len=strlen(s);for(int i=0;i<len;++i) pc(s[i]);}inline void write(const char *s){int len=strlen(s);for(int i=0;i<len;++i) pc(s[i]);}template<class T,class... Args> inline void write(T x,Args... args){write(x);write(args...);}
    }using namespace IO;
    const int N = 5e6 + 10;
    int fa[N],d[N],pru[N];
    priority_queue<int,vector<int>,greater<int> > q;
    signed main(){#ifndef ONLINE_JUDGEinfile("in.in");outfile("out.out");#else#endifint n,m;read(n,m);ll ans = 0;if(m == 1){for(int i = 1,x;i < n; ++i) read(x),++d[x],fa[i] = x;for(int i = 1;i <= n; ++i)if(!d[i]) q.push(i);int tot = 0;for(int i = 1;i <= n - 2; ++i){pru[i] = fa[q.top()];q.pop();if(!--d[pru[i]]) q.push(pru[i]);}for(int i = 1;i <= n - 2; ++i) ans ^= 1ll * i * pru[i];}else{for(int i = 1,x;i <= n - 2; ++i) read(x),pru[i] = x,d[x]++;for(int i = 1;i < n; ++i) fa[i] = n;for(int i = 1;i <= n; ++i) if(!d[i]) q.push(i);for(int i = 1;i <= n - 2; ++i){fa[q.top()] = pru[i],q.pop();if(!--d[pru[i]]) q.push(pru[i]);}for(int i = 1;i <= n - 1; ++i) ans ^= 1ll * i * fa[i];}write(ans);
    }
    

    还有一个\(O(n)\)的构造方法

    考虑删完一个点后,下一次改删哪个点,有两种情况,一是本来度数就为1的点,二是刚刚删完的点的父节点。

    维护一个指针,初始为1,每遇到一个度数为1的节点\(y\),就将其父节点\(x\)记录进\(prufer\)序列中,\(x\)的度数减一,若\(x\)的度数为1,则分类讨论。

    \(x>y\),继续自增。

    \(x<y\),另外处理\(x\),删除它,记录\(x\)的父节点

    重复以上操作。

    \(code:\)

    点此查看代码
    #include<bits/stdc++.h>
    #include<bits/extc++.h>
    // using namespace __gnu_pbds;
    // using namespace __gnu_cxx;
    using namespace std;
    #define infile(x) freopen(x,"r",stdin)
    #define outfile(x) freopen(x,"w",stdout)
    #define errfile(x) freopen(x,"w",stderr)
    using ll=long long;using ull=unsigned long long;
    char *p1,*p2,buf[1<<20];
    #define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
    #ifdef linux
    #define pc putchar_unlocked
    #else
    #define pc putchar
    #endif
    namespace IO{template<typename T>inline bool read(T &x){x=0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x<<1)+(x<<3)+(s^48);if(!f) x=~x+1;return true;}inline bool read(double &x){x=0.0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x*10)+(s^48);if(s!='.'){return true;}double res=0.1;s=gc();for(;'0'<=s&&s<='9';res/=10,s=gc()) x+=(s^48)*res;x=f?x:-x;return true;}inline bool read(long double &x){x=0.0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x*10)+(s^48);if(s!='.'){return true;}double res=0.1;s=gc();for(;'0'<=s&&s<='9';res/=10,s=gc()) x+=(s^48)*res;x=f?x:-x;return true;}inline bool read(float &x){x=0.0;char s=gc();bool f=true;for(;(s<'0'||'9'<s);s=gc()) {if(s=='-') f=false;if(s==EOF)return false;}for(;'0'<=s&&s<='9';s=gc()) x=(x*10)+(s^48);if(s!='.'){return true;}double res=0.1;s=gc();for(;'0'<=s&&s<='9';res/=10,s=gc()) x+=(s^48)*res;x=f?x:-x;return true;}inline bool read(string &str){string ().swap(str);char s=gc();for(;s==' '||s=='\n';s=gc());if(s==EOF) return false; for(;s!=' '&&s!='\n'&&s!=EOF;s=gc())str.push_back(s);return true;}inline bool read_line(string &str){string ().swap(str);char s=gc();for(;s==' '||s=='\n';s=gc());if(s==EOF) return false;for(;s!='\n'&&s!=EOF;s=gc()){str.push_back(s);}return true;}inline bool read_line(char *str){int len=0;char s=gc();for(;s==' '||s=='\n';s=gc());if(s==EOF) return false;for(;s!='\n'&&s!=EOF;s=gc()){str[len]=s;len++;}str[len]='\0';return true;}inline bool read(char &s){char x=gc();for(;x==' '||x=='\n';x=gc());if(x==EOF||x==' '||x=='\n')return false;s=x;return true;}inline bool read(char *s){int len=0;char x=gc();for(;x==' '||x=='\n';x=gc());if(x==EOF)return false;for(;x!=' '&&x!='\n'&&x!=EOF;x=gc())s[len++]=x;s[len]='\0';return true;}template<class T,class... Args> inline bool read(T &x,Args&... args){return (read(x)&&read(args...));}template<class T>inline void write(T x){static T st[45];int top=0;if(x<0)x=~x+1,pc('-');do{st[top++]=x%10;}while(x/=10);while(top)pc(st[--top]^48);}inline void write(char x){pc(x);}inline void write(string s){for(int i=0;s[i];++i) pc(s[i]);}inline void write(char *s){int len=strlen(s);for(int i=0;i<len;++i) pc(s[i]);}inline void write(const char *s){int len=strlen(s);for(int i=0;i<len;++i) pc(s[i]);}template<class T,class... Args> inline void write(T x,Args... args){write(x);write(args...);}
    }using namespace IO;
    const int N = 5e6+10;
    int fa[N],d[N],pru[N];
    signed main(){#ifndef ONLINE_JUDGEinfile("in.in");outfile("out.out");#else#endifint n,m;read(n,m);ll ans = 0;if(m == 1){for(int i = 1,x;i < n; ++i) read(x),fa[i] = x,++d[x];for(int i = 1,p = 1,x;i <= n - 2; ++i,++p){while(d[p]) ++p;pru[i] = fa[x = p];while(i <= n - 2 && !--d[pru[i]] && pru[i] < p) pru[++i] = fa[x = fa[x]];}for(int i = 1;i <= n - 2; ++i) ans ^= 1ll * i * pru[i];}else{for(int i = 1,x;i <= n - 2; ++i) read(x),pru[i] = x,++d[x];pru[n - 1] = n;for(int i = 1,p = 1,x;i <= n - 1; ++i,++p){while(d[p]) ++p;fa[x = p] = pru[i];while(i <= n - 1 && !--d[pru[i]] && pru[i] < p) fa[x = fa[x]] = pru[++i];}for(int i = 1;i <= n - 1; ++i) ans ^= 1ll * i * fa[i];}write(ans);
    }
    

凯莱公式

  • 内容:

    完全图\(k_n\)\(n^{n-2}\)棵生成树

  • 证明:

    任意一个长度为\(n-2\)的值域为\([1,n]\)的整数序列都可以通过\(Prufer\)序列双射对应一个生成树,于是方案数就是\(n^{n-2}\)

图连通方案数

  • 问题:

    一个\(n\)个点\(m\)条边的带标号无向图有\(k\)个连通块。添加\(k-1\)条边使得整个图连通。求方案数。

  • 证明:

    \(s_i\)为第\(i\)个连通块的数量,\(d_i\)为第\(i\)个连通块的度数,由于构造\(prufer\)序列的方案数为

    \[{k-2}\choose {d_1-1,d_2-1,...,d_k-1} \]

    对于第\(i\)个连通块,它的连接方式有\(s_i^{d_i}\)种,因此方案数为

    \[{{k-2}\choose {d_1-1,d_2-1,...,d_k-1}}\times\prod_{i=1}^ks_i^{d_i} \]

    枚举\(d\)序列,方案数有

    \[\sum_{d_i\ge 1,(\sum_{i=1}^kd_i)=2k-2}{{k-2}\choose {d_1-1,d_2-1,...,d_k-1}}\times\prod_{i=1}^ks_i^{d_i} \]

    换元,令\(a_i=d_i-1\),原式为

    \[\sum_{a_i\ge 0,(\sum_{i=1}^ka_i)=k-2}{{k-2}\choose {a_1,a_2,...,a_k}}\times\prod_{i=1}^ks_i^{a_i+1} \]

    利用多元二项式定理

    \[(x_1+x_2+\dots+x_n)^m=\sum\limits_{\sum_{i=1}^n d_i=m}\binom{m}{d_1,\dots,d_n}\prod_{i=1}^nx_i^{d_i} \]

    化简得

    \[(s_1+s_2+...+s_k)^{k-2}\times \prod_{i=1}^{k}s_i \]

    所以为

    \[n^{k-2}\times\prod_{i=1}^ks_i \]

    学这玩意就是为了这个式子

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/738190.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【冷启动#2】实用的springboot tutorial入门demo

跟着官方文档熟悉一遍创建spring工程的步骤 https://spring.io/guides/gs/spring-boot https://juejin.cn/post/7077958723829760008 demo简介 整个demo的预期目标是: 管理一堆玩家的数据,数据库使用的是现成的我们虚拟机上安装的MySQL 项目结构参考 主要工作:创建并熟悉spr…

CentOS8部署zerotier异地组网

本文介绍了在CentOS 8系统上部署ZeroTier以实现异地组网的方法,包括安装、配置、加入网络、开启IP转发和设置路由表等步骤,并提出进一步实现公网无缝组网的展望。CentOS8部署zerotier异地组网 CentOS8部署zerotier异地组网 一、前言 本文在此前研究部署FRP进行内网穿透,但FR…

《DNK210使用指南 -CanMV版 V1.0》第九章 打印输出实验

第九章 打印输出实验 1)实验平台:正点原子DNK210开发板 2)章节摘自【正点原子】DNK210使用指南 - CanMV版 V1.0 3)购买链接:https://detail.tmall.com/item.htm?&id=782801398750 4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/k210/ATK-DN…

分享一款可编辑本地电脑文件的在线编辑器

之前见过在线版的VSCode,被惊讶到了。网页上竟然可以编辑电脑本地的文件,打破了网页无法编辑本地电脑文件的限制。一直好奇怎么做的。抽空研究了一下,然后发现其实也不难。背景 之前见过在线版的VSCode,被惊讶到了。网页上竟然可以编辑电脑本地的文件,打破了网页无法编辑本…

xhcms

xhcms 目录结构 admin --管理后台文件夹 css --存放css的文件夹 files --存放页面的文件夹 images --存放图片的文件夹 inc --存放网站配置文件的文件夹 install --网站进行安装的文件夹 seacmseditor --编辑器文件夹 templ…

lrzsz安装完成后rz乱码

rz选择文件夹后乱码传输不到linux里面, 这时候只需要rz -be再选择文件 这样就可以进行后续的解压了tar -zxvf jdk-8u65-linux-x64.tar.gz

椭流线法设计配光器

本文介绍了利用椭流线法设计高效均匀的LED配光器,通过对边光原理、反射定律及椭圆几何特性的深入分析,结合Matlab和SolidWorks软件实现光学仿真,最终成功设计出接收效率高、均匀度优的配光器。椭流线法设计配光器 椭流线法设计配光器 一、设计原理 1、边光原理 边光原理是非…

wx云开发增删改查

首先是.wxml文件,此处为固定数据的新增<button type="primary" bind:tap="addData"> //调用.js中addData方法插入数据 </button>对应.js文件//添加数据addData(){wx.showLoading({ //showLoading(api接口)(防止用户多次…

剪裁法设计配光器

剪裁法设计配光器通过光源角分割和目标面分割,利用边光原理和反射定律,计算并构建光学母线,以实现高均匀度和高光效的均匀圆斑光学设计。剪裁法设计配光器 剪裁法设计配光器 一、设计原理边光原理 边光原理是非成像光学中的一个基础原理,其内容可以表述为:来自光源边缘的光…

iOS-列表视图

在iOS开发中,UITableView和UICollectionView是两个非常核心的用于展示集合数据的UI组件。它们都能以列表的形式展示数据,但各自的特点和使用场景有所不同。 UITableView UITableView用于展示和管理垂直滚动的单列数据列表。它是以行的形式展示数据,每行(cell)可以展示相同…

CPC配光系统设计

本文详细介绍了CPC(复合抛物线聚光器)配光系统的设计过程,包括设计原理、抛物流线几何特性及其设计要求和流程,并通过Matlab和SolidWorks绘制模型,最后在TracePro中进行仿真验证,确保系统满足均匀照度和高效接收率的目标。CPC配光系统设计 CPC配光系统设计 一、设计原理 …

VMware vSphere Tanzu部署_14_部署容器应用

1.部署运行容器应用 1.1. 登录tkc集群 jianhua@napp:~/tkc$ kubectl vsphere login --server=192.168.203.194 \ --tanzu-kubernetes-cluster-name tkc-dev-cluster \ --tanzu-kubernetes-cluster-namespace tkc-01 \ --vsphere-username administrator@vsphere.local \ --ins…

贝塞尔曲线原理、推导及Matlab实现

本文详细解析了贝塞尔曲线的定义、性质、构建方法以及多种阶数的推导公式,并提供了完整的Matlab代码用于绘制和计算贝塞尔曲线。贝塞尔曲线原理、推导及Matlab实现 贝塞尔曲线原理、推导及Matlab实现 一、简介 贝塞尔曲线提出 在数学的数值分析领域中,贝塞尔曲线(English:B…

刘积仁的大健康“长跑”

软件是一个长命的产业,但软件企业的寿命都很短。懂得怕死,才能有机会活得长久。 这一次,刘积仁又为东软医疗找到了强大助力!中国通用技术(集团)控股有限责任公司(以下简称通用技术集团)所属资本公司战略投资东软集团在医疗健康领域资的创新业务公司——东软医疗,双方也由…

【AppStore】一文让你学会IOS应用上架Appstore

咱们国内现在手机分为两类,Android手机与苹果手机,现在用的各类APP,为了手机的使用安全,避免下载到病毒软件,官方都极力推荐使用手机自带的应用商城进行下载,但是国内Android手机品类众多,手机商城各式各样,做不到统一,所以Android的APP上架得一个一个平台去申请上架,…

关于airtest生成的报告中缺少poco语句问题

1、airtest生成的报告只显示airtest的相关操作,如果是poco和airtest-selenium的操作则不记录。因此需要在报告中引用插件。支持poco语句插件,poco.utils.airtest.report 支持airtest-selenium语句插件,airtest_selenium.report2、在IDE运行 .py 脚本报告生成的依据是脚本运行…

xshell7的下载ssh远程连接

1.下载地址家庭/学校免费 - NetSarang Website (xshell.com) 2.下载后一路next,来到主页面,我们来连接一下试一试吧,这里主机就是ifconfig得到的 3.用户名一般都是root密码是自己设置的那个 4.连接的时候注意比如我要连接Node1那么node1就要保持开启并却防火墙已经关闭 5.看一…

xhcms1.0

xhcms1.0 目录结构 admin --管理后台文件夹 css --存放css的文件夹 files --存放页面的文件夹 images --存放图片的文件夹 inc --存放网站配置文件的文件夹 install --网站进行安装的文件夹 seacmseditor --编辑器文件夹 te…

关于巴图自动化Profinet协议转Modbus协议网关模块怎么配置IP地址教学

Profinet协议和Modbus协议是工业通讯常用协议,通过巴图自动化PN转Modbus网关模块(BT-MDPN10)实现连接。常见的协议有:ModbusTCP协议,Profibus协议,Profibus DP协议,EtherCAT协议,EtherNET协议,CAN,CANOPEN等Profinet协议和Modbus协议是工业领域中常用的两种通讯协议,…

基础篇:Stable Diffusion 基础原理详述

【基础篇】Stable Diffusion 基础原理详述前言我认为学习 ComfyUI 应该先从理论学起。与传统绘图工具(如 Photoshop 或 Figma)相比,AI 绘图工具有着显著不同。首先,许多设置和操作在 AI 绘图工具中是非可视化的,这意味着即使你更改了某个配置,界面上也未必会有任何变化,…