【树哈希】CF1182D Complete Mirror

CF1182D - Complete Mirror

Description

给定一个 n n n 个点的无根树,求一个树根 r o o t root root,使得对于任意两个节点 v 1 , v 2 v_1,v_2 v1,v2,若满足 d i s t ( v 1 , r o o t ) = d i s t ( v 2 , r o o t ) dist(v_1,root)=dist(v_2,root) dist(v1,root)=dist(v2,root),则必有 d g r ( v 1 ) = d g r ( v 2 ) dgr(v_1)=dgr(v_2) dgr(v1)=dgr(v2),无解输出 − 1 -1 1

d i s t ( u , v ) dist(u,v) dist(u,v)定义为 u , v u,v u,v 之间的边数, d g r ( v ) dgr(v) dgr(v) 定义为与 v v v 点直接相连的点的个数。


Solution

如果以某一个点为根时,树满足如上条件的充分必要条件为在第一个分叉点的所有儿子所构成的子树均为同构的。

例:

如图,第一个分叉点为 3 3 3 号点,所有儿子为 4 , 5 4,5 4,5 号点,显然他们所构成的子树是同构的。

那么,问题变成了如何找出第一个分叉点以及判断子树均同构

子树均同构

树哈希是解决这一类问题最有效的办法,当然树哈希也有好几种,这里小编采取 这一种。

不过,由于该题有换根操作,所以需要考虑如何换根:

d p ( u ) dp(u) dp(u) 表示以 u u u 为根的子树的哈希值,那么 d p ( u ) = ∑ v ∈ s o n ( u ) ( 1 + f ( d p ( v ) ) ) dp(u)=\sum_{v\in son(u)}(1+f(dp(v))) dp(u)=vson(u)(1+f(dp(v)))

对于一棵树:

如果从以 1 1 1 为根换到以 2 2 2 为根,那么哪些子树的哈希值会发生变化呢? 1 1 1 号和 2 2 2 号节点的子树的哈希值会发生变化,其余均不发生任何变化。

考虑 1 1 1 号节点子树哈希值:

  • 原来: d p ( 1 ) = 1 + f ( d p ( 2 ) ) + 1 + f ( d p ( 5 ) ) dp(1)=1+f(dp(2))+1+f(dp(5)) dp(1)=1+f(dp(2))+1+f(dp(5))
  • 现在: d p ( 1 ) = 1 + f ( d p ( 5 ) ) dp(1)=1+f(dp(5)) dp(1)=1+f(dp(5))

故,当 u u u 换根到 v v v 时, d p ( u ) = d p ( u ) − 1 − f ( d p ( v ) ) dp(u)=dp(u)-1-f(dp(v)) dp(u)=dp(u)1f(dp(v))

考虑 2 2 2 号节点子树哈希值:

  • 原来: d p ( 2 ) = 1 + f ( d p ( 3 ) ) + 1 + f ( d p ( 4 ) ) dp(2)=1+f(dp(3))+1+f(dp(4)) dp(2)=1+f(dp(3))+1+f(dp(4))
  • 现在: d p ( 2 ) = 1 + f ( d p ( 3 ) ) + 1 + f ( d p ( 4 ) ) + 1 + f ( d p ( 1 ) ) dp(2)=1+f(dp(3))+1+f(dp(4))+1+f(dp(1)) dp(2)=1+f(dp(3))+1+f(dp(4))+1+f(dp(1)),注意这里的 d p ( 1 ) dp(1) dp(1) 为更改后的 d p dp dp 值。

故,当 u u u 换根到 v v v 时, d p ( v ) = d p ( v ) + 1 + f ( d p ( v ) ) dp(v)=dp(v)+1+f(dp(v)) dp(v)=dp(v)+1+f(dp(v)),注意这里的 d p ( v ) dp(v) dp(v) 为更改后的 d p dp dp 值。

这样,就可以快速判断子树同构了!


第一个分叉点

这个确实不是很好直接干,直接干容易超时,不过转化一下:当以该分叉点为根时会发生什么?

若树为如下所示:

1 1 1 个分叉点为 3 3 3,将 3 3 3 为根时:

可以发现如果以分界点为根时,有 1 1 1 条链以及其余子树均同构,那么把这条链的端点移为根时,那么就是一颗满足条件的树,故这时候输出那条链的端点即可。

其余情况就判断所有儿子的子树是否均同构即可。更多小细节留给大家思考,这里不再赘述。


Code

其中代码前半段为取模板子,删掉后大概 112 112 112 行。

#include <bits/stdc++.h>
#define fi first
#define se second
#define int long longusing namespace std;typedef pair<int, int> PII;
typedef long long LL;const int MOD = 1e9 + 7;
int ksm(int a, int b) {int res = 1;while (b) {if (b & 1) res = res * a % MOD;a = a * a % MOD;b >>= 1;}return res;
}
void exgcd(int a, int b, int &x, int &y) {if (!b) {x = 1, y = 0;return;}exgcd(b, a % b, y, x);y -= a / b * x;
}
struct Mint {int v;void assign(int x) {v = x;}Mint operator+ (const Mint tmp)const {Mint res;res.v = (v + tmp.v) % MOD;return res;}Mint operator+ (const int tmp)const {Mint res;res.v = (v + tmp) % MOD;return res;}Mint operator- (const Mint tmp)const {Mint res;res.v = (v - tmp.v + MOD) % MOD;return res;}Mint operator- (const int tmp)const {Mint res;res.v = (v - tmp + MOD) % MOD;return res;}Mint operator* (const Mint tmp)const {Mint res;res.v = v * tmp.v % MOD;return res;}Mint operator* (const int tmp)const {Mint res;res.v = v * tmp % MOD;return res;}Mint operator/ (const Mint tmp)const {int x, y;exgcd(tmp.v, MOD, x, y), x = (x % MOD + MOD) % MOD;Mint res;res.v = v * x % MOD;return res;}Mint operator/ (const int tmp)const {int x, y;exgcd(tmp, MOD, x, y), x = (x % MOD + MOD) % MOD;Mint res;res.v = v * x % MOD;return res;}Mint operator^ (Mint b)const {Mint ans;ans.v = ksm(v, b.v);return ans;}Mint operator^ (int b)const {Mint ans;ans.v = ksm(v, b);return ans;}void read() {string s;cin >> s;for (auto i : s)v = (v * 10 + i - '0') % MOD;}
};const int N = 1e5 + 10;int n;
std::vector<int> G[N];
Mint dp[N];
int far[N];Mint h(Mint x) {return x * x * x * 1237123 + 1145141;
}
Mint f(Mint x) {Mint ok, res;res.v = 0;ok.v = (x.v & ((1ll << 31) - 1)), res = res + h(ok);ok.v = (x.v >> 31), res = res + h(ok);return res;
}
Mint dfs1(int u, int fa) {for (auto v : G[u]) {if (v == fa) continue;dp[u] = dp[u] + 1 + f(dfs1(v, u));}return dp[u];
}
void dfs2(int u, int fa) {unordered_map<int, int> cnt;int tot = 0;for (auto v : G[u]) {cnt[dp[v].v] ++, tot ++;}if (tot >= 3) {if (cnt.size() == 2) {for (auto v : G[u])if (cnt[dp[v].v] == 1 && far[v]) {cout << far[v] << endl;exit(0);}}if (cnt.size() == 1) {cout << u << endl;exit(0);}} else if (tot == 2) {if (cnt.size() == 1) {cout << u << endl;exit(0);}}for (auto v : G[u]) {if (v == fa) continue;Mint tmp1 = dp[u], tmp2 = dp[v];int tf1 = far[v], tf2 = far[u];dp[u] = dp[u] - 1 - f(dp[v]), dp[v] = dp[v] + 1 + f(dp[u]);if (G[u].size() == 2) {if (v == G[u][0] && far[G[u][1]]) far[u] = far[G[u][1]];if (v == G[u][1] && far[G[u][0]]) far[u] = far[G[u][0]];} else if (G[u].size() == 1) {far[u] = u;}far[v] = 0;dfs2(v, u);dp[u] = tmp1, dp[v] = tmp2, far[v] = tf1, far[u] = tf2;}
}
void dfs3(int u, int fa) {int tot = 0, p;for (auto v : G[u]) {if (v == fa) continue;tot ++, p = v;dfs3(v, u);}if (tot == 1) far[u] = far[p];if (tot == 0) far[u] = u;
}signed main() {cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);cin >> n;int u, v, fir = 0;for (int i = 1; i < n; i ++) {cin >> u >> v, G[u].emplace_back(v), G[v].emplace_back(u);if (!fir) fir = u;}dfs1(1, -1);dfs3(1, -1);if (far[1] || (G[1].size() == 2 && far[G[1][0]] && far[G[1][1]])) {if (far[1]) cout << 1 << endl;else cout << far[G[1][0]] << endl;return 0;}dfs2(1, -1);cout << -1 << endl;return 0;
}

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

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

相关文章

都2024年了,线上部署你不会只会log 调试吧,Arthas了解下!

文章目录 一、什么是Arthas&#xff1f;⛅背景⚡Arthas能为我们做什么 二、部署Arthas三、Arthas 基础命令四、Arthas 项目命令实战⌚thread 线程阻塞⏰watch命令演示⚡cpu飙升演示⛽方法演示 &#x1f6a8;小结 一、什么是Arthas&#xff1f; Arthas 是一款线上监控诊断产品&a…

[Linux][基础IO][一][系统文件IO][文件描述符fd]详细解读

目录 0.预备知识1.系统文件I/O1.open2.write/read/close/lseek 2.文件描述符fd1.[0 & 1 & 2]2.什么是文件描述符&#xff1f;3.文件描述符的分配规则4.重定向5.使用dup2系统调用 -- 完成重定向6.FILE 0.预备知识 什么叫做文件呢&#xff1f; 站在系统的角度&#xff0…

解放双手,批量绕过403

将dirsearch扫描出来的结果复制到url.txt&#xff0c;如下所示 url.txt [21:18:16] 502 - 0B - /var/log/exception.log [21:18:21] 502 - 0B - /WEB-INF/jetty-env.xml [21:18:22] 502 - 0B - /WEB-INF/weblogic.xml [21:18:27] 502 - 0B - /wp-json/wp/v2/u…

Android IPC机制

在Android系统中&#xff0c;IPC&#xff08;Inter-Process Communication&#xff0c;进程间通讯&#xff09;是指在不同进程之间传送数据和通讯的机制。Android中的应用通常运行在独立的沙箱环境中的进程里&#xff0c;由于安全限制&#xff0c;这些进程无法直接访问彼此的内…

Ubuntu 22.04 开机自动挂载webdav - 设置开机自启脚本 - 解决坚果云webdav无写入权限

效果图&#xff1a; 前言&#xff1a; 1&#xff09;亲测/etc/fstab的办法没有成功自动挂载&#xff0c;换成传统的rc.local可以解决&#xff1b; 2&#xff09;rc-local.service是系统自带的一个开机自启服务&#xff0c;但是在 ubuntu 20.04 上&#xff0c;该服务默认没有开…

基于JSP的教务管理

摘要 随着现代技术的不断发展&#xff0c;计算机已经深度的应用到了当下的各个行业之中&#xff0c;教育行业也不例外。计算机对教育行业中的教务管理等内容的帮助&#xff0c;使得教职工从传统的手工办公像计算机辅助阶段迈进&#xff0c;并且实现了非常好的发展。现在的学校…

SDK-0.8.8-Release-版本+ApiMeta - ApiHug-Release

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace ​ 更…

回溯算法中常见的使用方法逻辑整理

回溯算法 常见的使用方法逻辑整理 1. 回溯算法 特点 回溯算法实际上一个类似枚举的搜索尝试过程&#xff0c;主要是在搜索尝试过程中寻找问题的解&#xff0c;当发现已不满足求解条件时&#xff0c;就“回溯”返回&#xff0c;尝试别的路径。回溯法是一种选优搜索法&#xff0…

基于springboot实现师生共评作业管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现师生共评作业管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个专门适应师生作业交流形式的网站。本文介绍了师生共评的作业管理系统的开发全过程。通过分析企业对于师生共评的作业管理…

数据库:SQL分类之DQL详解

1.DQL语法 select 字段列表 from 表名列表 where 条件列表 group by 分组字段列表 having 分组后条件列表 order by 排序字段列表 limit 分页参数 基本查询 条件查询&#xff08;where&#xff09; 聚合函数&#xff08;count、max、min、avg、sum &#xff09; 分组查询&…

代码整洁?我后悔重构了代码

原文&#xff1a;Dan Abramov - 2020.01.11 那是一个深夜。 我的同事刚刚提交了他们一周编写的代码。我们正在开发一个图形编辑器的画布&#xff0c;他们实现了通过拖动边缘的小手柄&#xff0c;来调整形状&#xff08;如矩形和椭圆&#xff09;的大小的功能。 代码是有效的…

实习僧网站的实习岗位信息分析

目录 背景描述数据说明数据集来源问题描述分析目标以及导入模块1. 数据导入2. 数据基本信息和基本处理3. 数据处理3.1 新建data_clean数据框3.2 数值型数据处理3.2.1 “auth_capital”&#xff08;注册资本&#xff09;3.2.2 “day_per_week”&#xff08;每周工作天数&#xf…

TFT显示屏驱动

REVIEW 已经学习过VGA 时序与实现-CSDN博客 VGA 多分辨率-CSDN博客 今天就来让TFT屏显示一下 ACZ702开发板管脚信息表 - ACZ702开发板 - 芯路恒电子技术论坛 - Powered by Discuz! (corecourse.cn) 小梅哥视频&#xff1a;24 RGB TFT显示屏原理与驱动实现_哔哩哔哩_bilibili …

活动图高阶讲解-16

77 00:05:39,520 --> 00:05:41,520 另外一个就是循环 78 00:05:41,520 --> 00:05:45,520 如果怎么样 79 00:05:45,520 --> 00:05:47,520 就再做一遍 80 00:05:47,520 --> 00:05:49,520 如果还满足条件就再做一遍 81 00:05:49,520 --> 00:05:51,520 那就是循…

TG-12F使用SDK对接阿里生活物联网平台

文章目录 前言一、注意二、准备1. 安装Ubuntu&#xff08;版本20.04 X64&#xff09;程序运行时库。按顺序逐条执行命令&#xff1a;2. 安装Ubuntu&#xff08;版本20.04 X64&#xff09;依赖软件包。按照顺序逐条执行命令&#xff1a;3. 安装Python依赖包。按照顺序逐条执行命…

[spring] Spring Boot REST API - CRUD 操作

Spring Boot REST API - CRUD 操作 这里主要提一下 spring boot 创建 rest api&#xff0c;并对其进行 CRUD 操作 jackson & gson 目前浏览器和服务端主流的交互方式是使用 JSON(JavaScript Object Notation)&#xff0c;但是 JSON 没有办法直接和 Java 的 POJO 创建对应…

python-numpy(3)-线性代数

一、方程求解 参考资料 对于Ax b 这种方程&#xff1a; np.linalg.inv(A).dot(B)np.linalg.solve(A,b) 1.1 求解多元一次方程一个直观的例子 # AXB # X A^(-1)*B A np.array([[7, 3, 0, 1], [0, 1, 0, -1], [1, 0, 6, -3], [1, 1, -1, -1]]) B np.array([8, 6, -3, 1]…

cannot import name ‘get_host‘ from ‘urllib3.util.url‘

Error in py_module_import(module, convert convert) : ImportError: cannot import name get_host from urllib3.util.url (D:\\url.py) Run reticulate::py_last_error() for details. 这个错误表明在 urllib3 模块的 util.url 子模块中找不到名为 get_host 的函数。这可能…

第十五届蓝桥杯省赛C/C++大学B组真题及赛后总结

目录 个人总结 C/C 组真题 握手问题 小球反弹 好数 R 格式 宝石组合 数字接龙 爬山 拔河 ​编辑 再总结及后续规划 个人总结 第一次参加蓝桥杯&#xff0c;大二&#xff0c;以前都在在学技术&#xff0c;没有系统的学过算法。所以&#xff0c;还是花了挺多时间去备…

Rust - 所有权

所有的程序都必须和计算机内存打交道&#xff0c;如何从内存中申请空间来存放程序的运行内容&#xff0c;如何在不需要的时候释放这些空间&#xff0c;成了重中之重&#xff0c;也是所有编程语言设计的难点之一。在计算机语言不断演变过程中&#xff0c;出现了三种流派&#xf…