妙妙子树上好题 XOR, Tree, and Queries
迪丽瓦拉
2025-05-28 19:52:40
0

XOR, Tree, and Queries

大意:
给定一棵树n个节点,然后告诉你m个点对之间的简单路径异或和。要求构造出满足条件的一棵树,使得所有边权满足条件,且所有边权的异或和尽可能小

思路:

实在妙妙子,我看到构造所有边权就是直接傻眼,寻思线性基还是trie好像都不能给出构造方案。没想到题目只用了异或的最简单的性质,加上反常的建图,就解决了...

首先树上异或的话,一个常见的trick就是做根到节点的前缀异或和。我们记pi表示根节点到i的路径上的边权异或和,那么不难发现,对于任意两个节点u,v,它们之间的简单路径异或和可以按如下方式转化

 等于u-lca的路径与lca-v的异或和,也就是\large p_u\oplus p_{lca}\oplus p_v\oplus p_{lca}=p_u \oplus p_v

如果我们已知u到v的路径异或和是x,则\large p_u \oplus p_v=x\Rightarrow p_u=p_v\oplus x

所以我们可以通过上述结论来尝试推出对应节点的值。

所以,我们可以按给的边权异或和关系来重新建图,这样会得到一个个连通块。每一个连通块内,我们从任意一个起点出发(不妨假设它的pi值为0,这当然是合理的,因为想要修改它为x的话,我们只要让连通块内的点的p值都异或上x就可以了。个人感觉这里并不好想,因为完全是在两个不同的图上面考虑,这里的修改权值意味着在树上一大段路径的修改。但是我们在推的时候肯定是保证了可行性,而我们不用找到具体的构造方案,只要它一定存在就可以了),可以推出其余点的p值,然后,如果里面有环,并且发现某一个点从不同路径走有不同值时,意味着该情况无解,这题就结束了。否则,我们就能得到一组满足条件的边权。

然后考虑题目的另一个约束条件:边权的异或和最小。

套用上述结论,对于相邻节点u,v,\large e_{u,v}=p_u \oplus p_v,所以我们可以将所求式子改写

\large e_1 \oplus e_2 ... \oplus e_{n-1}=(p_{u_{1}}\oplus p_v_{1})\oplus (p_{u_{2}}\oplus p_v_{2})...(p_{u_{n-1}}\oplus p_v_{n-1})

显然每一个pi有贡献当且仅当它出现次数为奇数,也就是i节点的度数为1

所以我们把所有度数为1的节点找出来,它们的异或和,就是我们的答案。

然后要优化的话,我们一定是在每一个连通块里统一异或上一个值。如果某一个连通块的大小是偶数,意味着我们要修改的值x会异或上偶数次,相当于没有操作。所以大小为偶数的连通块堆我们没帮助。

而一旦出现大小为奇数的连通块,也就是最后结果会异或上我们的修改值x。我们只要让x等于当前答案,那么最后的总体异或值就是0了。此时我们只要在该连通块内修改每一个点的p值,就能退出得到所有边权了。

所以,看起来是一道很伤脑筋的构造题,其实最后的结果只有三种情况:无解,0,一个常值。

至于前面的如何在一个连通块内推出所有值,dfs一下即可,有点像染色。我也看到过有人是拆开按位考虑,然后每一位就变成了0或者1的情况,那样就是二分图染色来标记了。

直接做的话,我们的复杂度可以来到喜人的O(n)

code

#include
using namespace std;
#define ll long long
#define endl '\n'
const ll N=3e5+10;
struct ty
{ll t,l,next;
}edge[N<<1];
ll cn=0;
ll head[N];
void add(ll a,ll b,ll c)
{edge[++cn].t=b;edge[cn].l=c;edge[cn].next=head[a];head[a]=cn;
}
ll e1[N],e2[N];
ll fl[N];//度数为奇数的话就标记 
ll n,m;
ll vis[N];
ll p[N];//答案 
ll siz[N];
void dfs(ll id,ll k)
{vis[id]=k;for(int i=head[id];i!=-1;i=edge[i].next){ll y=edge[i].t;if(vis[y]==0){p[y]=p[id]^edge[i].l;dfs(y,k);}else if(p[y]!=(p[id]^edge[i].l)){cout<<"No"<>n>>m;for(int i=1;i>e1[i]>>e2[i];fl[e1[i]]^=1;fl[e2[i]]^=1;}for(int i=1;i<=m;++i){ll a,b,c;cin>>a>>b>>c;add(a,b,c);add(b,a,c);}for(int i=1;i<=n;++i){if(vis[i]) continue;dfs(i,i); }ll ans=0;for(int i=1;i<=n;++i){if(fl[i]) ans^=p[i],siz[vis[i]]++;}for(int i=1;i<=n;++i){if(siz[i]%2==0) continue;//cout<<"df "<

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...