P10451 做题随笔

news/2025/2/11 17:20:28/文章来源:https://www.cnblogs.com/Tenil/p/18710156

Solution

题意

原题链接

对每组数据,给定两颗用 01 序列描述的树,描述规则如下:

  1. 按照 \(\text{DFS}\) 序进行遍历;
  2. 若序列中某位为 0,表示除根节点外的节点进栈;为 1 则表示出栈。

要求判断一树是否可以通过交换子树的方式变换成另一子树(对于本题,即两树同构)。

分析

1. 朴素算法

从上述概念,自然可以得到两树 \(T_1,T_2\) 同构的必要条件:\(T_1\)\(T_2\) 有且仅有以下三种关系:

  1. 均为空;
  2. 二者全等;
  3. 交换子树后全等。

于是自然可以想到对每组数据分别建树,然后递归验证以上条件进行判断。验证部分伪代码如下:

chk(f1,f2)//f1,f2 表示当前 T1,T2 正验证的结点编号if son[f1]==son[f2]=∅//son[f] 表示 f 的儿子的点集return true;else if son[f1]=∅ or son[f2]=∅return false;for each x ∈ son[f1]for each y ∈ son[f2]return chk(son[f1],son[f2])

随便想想都感觉会炸,下面会介绍能过的算法。

其实判断树同构还有更好的算法,如 \(\text{AHU}\) 算法(如果学过的童靴就会发现,其实本题的输入就和暴力 \(\text{AHU}\) 的结点特征名很像)或者树哈希,可以 \(O(n)\)\(O(n \log n)\) 完成。但是考虑到这只是个普及/提高-,只留链接供大家了解 AHU。

2. 针对此题的特解

根据上文的代码可以发现,由于本题点和边都没有特征,判同构只需判断某个地方是否存在一个点,由此本题有了优化空间。

这里给出一个判准:将树上所有节点表示为 \((dep,sz)\) (深度,子树大小的有序数对),若如此表示的两树结点的集合相同,则两树同构。

以下是证明:

考虑归纳。已有树 \(T_1,T_2\),高度为 \(h\),考虑判断两树是否同构:

\(h=1\),显然成立;

\(h=k\) 时成立,对 \(h=k+1\)

首先,同构是具有传递性的,因为“交换”是无序的;然后,高度为 2 的子树的叶子结点数是只取决于树根的 \(sz\) 值的,这是显然的。

由于 \(h=k\) 时同构,不妨从高层至低层地,将 \(T_1,T_2\)\(k\) 层中,同子树内结点按 \(sz\) 降序从左至右排序,于是树上结点的 \(sz\) 相对位置确定。(这步相当于数学的设序,只是为了方便之后论述)

为了证明本结论,假设 \(T_1\) 已有第 \(k+1\) 层而 \(T_2\) 还只有已经证明为同构的前 \(k\) 层。现在在 \(T_2\)\(k\) 层叶子结点上接入第 \(k+1\) 层的新叶子结点,对于第 \(k\) 层的某点,其在 \(T_1\) 中的 \(sz\) 确定,故以其子节点的数量确定,接上对应数量的叶子即可。随后再次按照上述方式排序,得到新树是同构于 \(T_1\) 的,故新树与排序前的 \(T_1\) 同构。

即证。

看着可能比较模糊,这里是图。考虑如此的 \(T_1\)

如此的 \(T_2\)

\(T_2\) 的最左侧叶子加点,应加 \(4-1=3\) 个叶子,这是确定的。类似地添加其他点,最后一定可以得到同构树。

论述可能有点不严谨,于是蒟蒻用树哈希的标程(感谢@wt1551大佬)进行了 \(n=50\),结点数为 1000 的 13000 组随机数据,结论具有一定可靠性。(或者亦可证明:对于此题,子树大小可以作为 \(\text{AHU}\) 的结点特征序)

实现

\(\text{DFS}\) 遍历序列,不建树,但是记录每个节点的深度和以他为根的子树大小,两树比较即可。

另:对于输入序列,有:一个完整子树中的 0 和 1 数量相同,且 0(或 1)的数量等于子树大小,代码还可简化,等待好心人写一个?

Code

#include <iostream>
#include <cstdio>
#include <cctype>
#include <vector>
#include <string>
#include <algorithm>using namespace std;typedef long long ll;ll n;
string s[2];
vector<pair<ll,ll> > v[2];pair<ll,ll> dfs(int dep,int pos,int i) {int size=1;while(s[i][pos]!='1') {pair<ll,ll> now=dfs(dep+1,pos+1,i);pos=now.first;size+=now.second;}v[i].push_back(make_pair(dep,size));return make_pair(pos+1,size);
}int main() {n=fr();while(n--) {v[0].clear();v[1].clear();cin >> s[0] >> s[1];s[0]+="1";s[1]+="1";if(s[0].length()==s[1].length()) {bool flag=true;dfs(1,0,0);dfs(1,0,1);sort(v[0].begin(),v[0].end());sort(v[1].begin(),v[1].end());for(register int i = 0; i < (int)v[0].size(); i++) {if(v[0][i]!=v[1][i]) {printf("different\n");flag=false;break;}}if(flag) printf("same\n");}else {printf("different\n");}}return 0;
}

闲话

如果觉得有用,点个赞吧!

有 hack 的话请艾特我一下!

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

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

相关文章

堆排序--代码实现

本文主要说明代码编写思路和具体代码,下面的博文讲的比较全面 参考文章:https://www.cnblogs.com/jingmoxukong/p/4303826.html代码思路(以大根堆为例) 堆排一共分2个阶段:1. 创建一个大根堆 2.交换堆顶和堆尾元素,获取到堆顶元素,并重新维护大根堆 第一个阶段的思路: 从…

贪心tricks总结

贪心题一般没有什么技巧,多做题积累经验。 对于结论或策略,大胆猜想,小心求证,注意使用数据结构优化/结合其他算法。 一般类贪心 主要是证明贪心的正确性。 H. Fight Against Monsters 先用二分求出每个怪需要打的次数。 问题转化为一个排列的答案是 \[\sum_{i=1}^{n} \sum…

dp优化之斜率优化小结

这或许是这几天的济南云斗集训之旅最大的收获吧,若是最后一天的模拟赛文件不会交错也许结局会更好,但在这残酷的现实中却从不会有“如果”一词,母亲以不想让我学了,或许考完今年的 CSP 就可能不学了吧。 本文将效仿《李煜东算法进阶指南》的思路,按照例题层层深入。 P2365…

P3406 海底高铁(差分)

这道题要用到差分,因为反复经过一条路时只需要买一张对应的卡就行了,不用买多张,所以我们可以用差分,算出经过每条路的次数,要注意假设从1到3城市,只经过了道路1和道路2,应该让cha【1】++,cha【3】--; 还有算结果时应该从1到n-1列举每一条路,我最开始就搞错了,还要注…

JPlag:开源的代码抄袭检测工具

一、基本信息•项目地址: https://gitcode.com/gh_mirrors/jp/JPlaghttps://github.com/jplag/JPlag•编程语言:基于Java开发•主要特性:跨平台运行、支持多种文件格式、提供图形用户界面(GUI)和命令行接口、可扩展性强 二、技术特点 •多语言支持:JPlag支持包括Java、C、…

重构谷粒商城01:为何重构谷粒商城

前言:这个系列将使用最前沿的cursor作为辅助编程工具,来快速开发一些基础的编程项目。目的是为了在真实项目中,帮助初级程序员快速进阶,以最快的速度,效率,快速进阶到中高阶程序员。 本项目将基于谷粒商城项目,并且对谷粒商城项目进行二次重构,使其满足最新的主流技术栈…

div设置四个角边框

示例实现 .top-header {background-image:url(../../assets/slider/topHeaderTopLeft.svg), /* 左上角图像 */url(../../assets/slider/topHeaderTopRight.svg), /* 右上角图像 */url(../../assets/slider/topHeaderBottomLeft.svg), /* 左下角图像 */url(../../assets/slider/…

JavaScript根据访问链接不同的后缀参数,展示不同的页面

要求:根据访问者访问不同的后缀链接,展示不同的页面;$(document).ready(function () {// 获取 URL 参数const urlParams = new URLSearchParams(window.location.search);const page = urlParams.get(page) || model; // 默认显示第一个导航项(比分)的内容和图标$(.tab-co…

内外网文件传输方案

文件传输问题:企业内网和外网分开了,如何进行文件快速有效稳定的传输呢?如何 进行文件交换、在线审批、在线审计呢?如何保证安全可控的文件传输、性能及扩展性强、审批审计便捷呢?常见痛点有哪些?纸质申请、线下审批、传递效率很慢,传递成本高, 纸质单据与电子文件脱节…

H3C--堆叠(IRF)

拓扑图 配置流程 配置SW1与SW2堆叠 一、SW1:shutdown 物理端口 配置堆叠优先级,优先级高的成为主设备 创建堆叠逻辑接口,将物理接口加入到堆叠逻辑接口中二、SW1: sysname SW1#irf member 1 priority 6#irf-port 1/1 port group interface FortyGigE1/0/53 port group int…

JavaScript判断iPhone型号机型及iPhone版本Identifier对照

要求:根据用户安装App后,返回的设备型号,判断iPhone版本 实现代码:function getModelValue(last_model) {// 如果last_model不包含"iPhone",则直接返回原值if (!last_model.includes(iPhone)) {return last_model;}// 定义子字符串和对应值的全面映射const mode…

linux部署nacos集群

本次部署 3个nacos节点,然后一个负载均衡器(nginx)代理3个Nacos。集群部署按照前述,做好数据库脚本的初始化、防火墙策略的设置。安装jdk 解压jdk文件 cd /data/soft tar -zxvf jdk-23_linux-x64_bin.tar.gz修改环境变量 vi /etc/profile#install JAVA JDK export JAVA_HOM…