题解:P13266 [GCJ 2014 Finals] Symmetric Trees

news/2025/11/27 21:50:09/文章来源:https://www.cnblogs.com/dyc2022/p/19279550

更差的阅读体验


NOIP2025 RP++ 喵。


考虑哈希。

假设 \(c_i\) 为节点 \(i\) 的颜色。

首先为了避免冲突,我们将 \(c_i\) 映射成随机大整数。然后我们构造一个哈希函数,既能体现出树的形态,又能体现点的颜色。可以这样:

\[\operatorname{hash}(u) = c_u + \sum_{v \isin \operatorname{son}_u} \operatorname{shift}(\operatorname{hash}(v)) \]

\(\operatorname{shift}\) 是一些异或位移操作,也可以认为是一种映射。

接下来无非就两种情况:对称中心是点,对称中心是边。

  • 如果对称中心是点,那么这个点 \(u\) 的子树一定可以两两配对,直到剩下零个或一个或两个子树。
    • 我们想到一个看起来很聪明的方法:记录一个点所有子树哈希值的 \(\operatorname{xor}\)
      • 如果最后剩下 \(0\) 个子树,那么异或值为 \(0\),相当好判断。
      • 如果最后剩下 \(1\) 个子树,那么异或值就是剩下的一个子树的哈希值。需要满足这个子树本身是对称的。在实现中可以开一个类似 map 的数据结构来存。
      • 如果最后剩下 \(2\) 个子树,看起来不太好处理。但是仔细想一下,如果真的剩下两个对称的子树,我们可以把对称中心沿着其中一棵子树往下跳,直到跳到分岔的地方。这个时候就变成了剩下 \(1\) 个子树的情况。所以不需要特别处理这种情况。
  • 如果对称中心是边,那很简单,只要看边两端的哈希值是否相等就可以了。

至此可以做到 \(O(n^2)\):枚举对称中心,每次重新计算哈希值。

但是还不够。

考虑换根 dp。我们考虑 \(f_u\) 表示钦定 \(1\) 为根,\(u\) 子树的哈希值,\(g_u\) 表示钦定 \(u\) 为根,整棵树的哈希值。

\(f\) 是好求的。假设 \(fa_u\) 表示 \(u\) 的父亲,那么我们把 \(g\)\(fa_u\) 转移到 \(u\),需要在继承之前 \(f_u\) 的信息的基础上,加入 \(fa_u\) 所在子树的信息。

由于我们之前是求和计算哈希值,所以父亲的哈希值是很好算的,直接拿 \(g_{fa_u}\) 减去 \(f_u\) 即可。

但是上面的讨论中,我们还要把所有对称的子树抠出来扔到 map 里面,所以我们还要同时记录一棵子树是否合法。判断一个大子树抠掉一个小子树是否合法也是容易的。

然后就变成基础的换根了。我们可以全局维护一下每个点邻居的异或值,还有每个点周围对称子树的 map。我在实现中其实用了 unordered_map,这样可以认为是线性的。

这道题就做完了,复杂度 \(O(n)\)

#include<bits/stdc++.h>
#define endl '\n'
#define N 10006
using namespace std;
using ull=unsigned long long;
mt19937_64 rnd(time(0));
struct Node{ull has; int o;} f[N],g[N];
ull refer[206],a[N],xor_sum[N];
int n,ok; char ch[3];
vector<int> G[N];
unordered_map<ull,int> mp[N];
inline ull shift(ull x)
{x^=x<<13,x^=x>>17,x^=x<<5;return x;
}
int check(int u,ull cut)
{ull new_xor=xor_sum[u]^cut;int new_cnt=mp[u][new_xor]-(new_xor==cut);if(!new_xor||new_cnt)return 1;return 0;
}
void dfs1(int u,int fa)
{f[u].has=a[u];for(int v:G[u])if(v!=fa)dfs1(v,u),f[u].has+=shift(f[v].has);unordered_map<ull,int> mp; ull xor_sum=0;for(int v:G[u])if(v!=fa&&f[v].o)mp[f[v].has]++;for(int v:G[u])if(v!=fa)xor_sum^=f[v].has;if(!xor_sum||mp[xor_sum])f[u].o=1;else f[u].o=0;
}
void dfs2(int u,int fa)
{if(fa){Node hf; hf.has=g[fa].has-shift(f[u].has);if(hf.has==f[u].has)ok=1;hf.o=check(fa,f[u].has),g[u].has=a[u];for(int v:G[u]){Node now=(v==fa?hf:f[v]); g[u].has+=shift(now.has);if(now.o)mp[u][now.has]++;xor_sum[u]^=now.has;}g[u].o=check(u,0);if(g[u].o)ok=2;} else for(int v:G[u]) {if(f[v].o)mp[u][f[v].has]++;xor_sum[u]^=f[v].has;}for(int v:G[u])if(v!=fa)dfs2(v,u);
}
void solve(int _)
{scanf("%d",&n),ok=0; if(_==17)cerr<<n<<endl;for(int i='A';i<='Z';i++)refer[i]=rnd();for(int i=1;i<=n;i++)scanf("%s",ch+1),a[i]=refer[ch[1]],G[i].clear(),mp[i].clear(),xor_sum[i]=0;for(int i=1,u,v;i<n;i++)scanf("%d%d",&u,&v),G[u].push_back(v),G[v].push_back(u);dfs1(1,0),g[1]=f[1],dfs2(1,0);printf("Case #%d: ",_);printf(ok?"SYMMETRIC\n":"NOT SYMMETRIC\n");
}
main()
{int T,_=0; scanf("%d",&T);while(T--)solve(++_);return 0;
}

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

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

相关文章

python---深拷贝浅拷贝

这是笔记了啦,有点乱,感觉面试会必背赋值 lis1 = [1,2,3,4,5] lis2 = lis1 #将lis1赋值给lis2 #给lis1新增元素 lis1.append(6) print(新增后的lis1,lis1) print(新增后的lis2,lis2) #新增后的lis1 [1, 2, 3, 4, 5,…

解决ARM Linux下使用PlatformIO 找不到编译工具链toolchain报错

问题描述 在ARM架构的Debian12上使用PlatformIO开发STM32遇到如下报错PIO Core Call Error: "Platform Manager: Installing ststm32\nPlatform Manager: ststm32 @ 10.0.1 has been installed!\nTool Manager: I…

搜维尔科技:新一代Xsens Link动作捕捉系统,非常适合实时机器人远程操控、虚拟制作和现场演出录制

值得信赖的动作捕捉标准,经过重新设计,可适应人类的各种运动方式。十多年来,Xsens Link为包括人形机器人、电影、生物力学、游戏开发和运动表现等在内的众多行业提供动作捕捉技术支持。 凭借其卓越的性能,Xsens Li…

logback日期格式

通过在 Logback 的 pattern 中使用 %d{yyyy-MM-dd HH:mm:ss.SSS, XXX} 配置的: 具体配置方法 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS, XXX} [%thread] %-5level %logger{36} - %msg%n</pattern>完整的 log…

Codeforces Round 1066 (Div. 1 + Div. 2) 比赛总结

比赛链接 Result爽掉 \(11\) 分,再这么打下去要掉成青了…… Solution D - Billion Players Game 可以发现绝对值没有任何用,第一种操作收益一定为 \(a_i-p\),第二种操作收益一定为 \(p-a_i\)。把 \(a_{1\sim n}\) …

10424_基于Springboot的物流管理系统

1、项目包含 项目源码、项目文档、数据库脚本、软件工具等资料; 带你从零开始部署运行本套系统。 2、项目介绍 随着社会的发展,计算机的优势和普及使得智能物流管理系统的开发成为必需。智能物流管理系统主要是借助计…

解决VirtualBox - Error In supR3HardenedWinReSpawn报错

解决步骤选择Virtualbox目录下的\drivers\vboxsup\VBoxSup.inf(旧版本是VBoxDrv.inf),右键选择安装打开注册表编辑器打开路径HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VBoxSup#旧版本是 HKEY_LOCAL_M…

1127随笔

这几天上网上查了下怎么整ai接口 最后也算是完成了调用免费ai创建故事与生成图片,并成功保存在数据库里。 要说难点的话,应该就是功能在网页上的集成吧。

大规模微服务强大的系统中的雪崩故障防治

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

flutter 生命周期管理:从 Widget 到 State 的完整解析 - 指南

flutter 生命周期管理:从 Widget 到 State 的完整解析 - 指南2025-11-27 21:27 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !impor…

python写入csv代码

import csv import osdef save_to_csv(book_list):with open(books.csv,w,newline=, encoding=utf-8-sig) as csvfile:writer=csv.DictWriter(csvfile,fieldnames=[书名, 作者, ISBN, 价格,库存])writer.writeheader()…

gradle的各个环境依赖jar包的同一个版本导致的严重后果

背景:我司的A项目(gradle)、B项目(maven),且公司无maven私服,jar包均放在gitlab的项目的package registry中A项目依赖B项目的api包,我的做法如下:B项目版本定义成1.0-SNAPSHOT版本,永远都是这个版本 在gitla…

20251127

我这个忘浑蛋又忘了写博客了,最近想弄个远程服务器试试javaweb,阿里云好像有学生特权,一会儿去看看。

一定要扪心自问

你如果还只是理解的那么片面,学了那么多有什么用 一定要思考 就像这道题吧: 1.min考虑的是初始值0x3f3f3f3f; 2.选了和没选而不是无脑的dp[][]; 不可以再像之前一样永远无脑的dp[][]!!!; #include <bits/stdc++.h…

2025年租房APP推荐:官方测评与精选攻略

2025年租房APP推荐:官方测评与精选攻略在城市青年的居住选择谱系中,租房早已不再是“找个落脚处”那么简单。信息冗杂的品牌公寓、良莠不齐的中介平台、真假难辨的个人房源,将租客推向一场耗时耗力的拉锯战。人们不…

Day26字体图标--上传矢量图

上传矢量图是为了解决项目需要的图片到iconfont图标库,生成字体 首先上传图片的后缀要是svg 进入inconfont之后寻找这个图标从左往右数第一个云朵样式的 点击之后从文件夹选择要上传的图标即可

从零开始:用Python和Gemini 3四步搭建你自己的AI Agent

很多人第一次看到 AI Agent 自己编辑文件、跑代码、修 bug,还能一直运行下去的时候,都觉得挺神奇。其实远没有想象中那么复杂。这里没什么秘密算法,也没有什么"智能体大脑"这种玄学概念。 AI Agent核心就三…

【机器学习】突破分类瓶颈:用逻辑回归与Softmax回归解锁多分类世界 - 指南

【机器学习】突破分类瓶颈:用逻辑回归与Softmax回归解锁多分类世界 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-famil…

双特异性抗体:抗癌 “双面手”,两种模式精准杀伤癌细胞

双特异性抗体是免疫治疗的 “升级款利器”,能同时精准结合两种不同抗原或表位 —— 既可以是同一癌细胞上的两个靶点,也能是癌细胞与免疫细胞上的不同靶点,通过两种核心作用模式,实现对癌细胞的高效杀伤,比单特异…

机器翻译模型跨领域自适应技术解析

本文介绍了一种结合弹性权重巩固与数据混合的神经机器翻译多领域自适应方法,有效平衡新旧任务性能,在EMNLP 2021会议上发表的研究成果。适应机器翻译模型到新领域 结合弹性权重巩固和数据混合能在旧任务和新任务性能…