当前位置: 首页 > news >正文

千问 LeetCode 3887. 增量偶权环查询 C++实现

这道题的核心是带权并查集,将"环边权和为偶数"转化为"环上边权异或和为 0",通过维护每个节点到根的异或距离来判断新边是否会形成奇权环。

核心思路

1. 问题转化:边权为 0 或 1,环的边权和为偶数 ⟺ 环上所有边权的异或和为 0
2. 维护目标:如果图中所有环的异或和都为 0,那么任意两点间任意路径的异或和都是唯一确定的(与路径无关)
3. 带权并查集:用 fa[x] 记录父节点,dis[x] 记录 x 到父节点路径上的边权异或和。通过路径压缩,find(x) 后 dis[x] 就是 x 到根的异或距离
4. 判断逻辑:对于边 (u, v, w),若 u、v 已在同一集合,检查 dis[u] ^ dis[v] ^ w 是否为 0;为 0 说明新环异或和为偶数,可加入;否则会产生奇权环,跳过

C++ 实现

class Solution {
vector<int> fa, dis; // dis[x]: x 到 fa[x] 路径上的边权异或和

// 带路径压缩的 find,调用后 dis[x] 变为 x 到根的异或距离
int find(int x) {
if (fa[x] != x) {
int root = find(fa[x]);
dis[x] ^= dis[fa[x]]; // 累积异或距离
fa[x] = root;
}
return fa[x];
}

public:
int numberOfEdgesAdded(int n, vector<vector<int>>& edges) {
fa.resize(n);
dis.assign(n, 0);
for (int i = 0; i < n; i++) fa[i] = i;

int count = 0;
for (auto& edge : edges) {
int u = edge[0], v = edge[1], w = edge[2];
int ru = find(u), rv = find(v);

if (ru == rv) {
// 已在同一集合:检查新环的异或和
// 环的异或和 = dis[u] ^ dis[v] ^ w
if ((dis[u] ^ dis[v] ^ w) == 0) {
count++; // 偶权环,可以加入
}
// 否则产生奇权环,跳过
} else {
// 不在同一集合:合并,不会形成环
// 需要让 dis[u] ^ dis[v] ^ w = 0 成立
// 即 dis[ru] = dis[u] ^ dis[v] ^ w
dis[ru] = dis[u] ^ dis[v] ^ w;
fa[ru] = rv;
count++;
}
}
return count;
}
};

关键点解析

- 路径压缩时的异或更新:dis[x] ^= dis[fa[x]] 是因为 x 到根的异或距离 = x 到旧父节点的异或 ⊕ 旧父节点到根的异或
- 合并时的权重设置:合并 ru 和 rv 时,设置 dis[ru] = dis[u] ^ dis[v] ^ w,保证合并后 u 和 v 之间的异或距离恰好等于 w
- 时间复杂度:O(m · α(n)),其中 m 是边数,α 是反阿克曼函数,近似线性
- 空间复杂度:O(n)

示例验证

以 n=3, edges=[[0,1,1],[1,2,1],[0,2,1]] 为例:

1. 边 (0,1,1):0 和 1 不在同一集合,合并,count=1
2. 边 (1,2,1):1 和 2 不在同一集合,合并,count=2
3. 边 (0,2,1):0 和 2 已在同一集合,环异或和 = dis[0]^dis[2]^1 = 1^1^1 = 1(奇数),跳过

最终返回 2,与预期一致。

需要我帮你整理一份带权并查集(异或/加法)的通用模板吗?遇到类似题可以直接套用。

http://www.jsqmd.com/news/1388126/

相关文章:

  • 2026年7月南京市六合区二手房价格深度分析报告
  • Zabbix Proxy分布式监控 Grafana数据可视化
  • 2026深圳写字楼搬迁正规公司挑选全攻略:从资质核查、书面报价到夜间施工报备,附全区域收费标准与避坑指南(福田/南山/宝安/龙岗适用) - 禧燕搬家
  • API安全漏洞剖析:从授权检查缺失看业务逻辑风险防范
  • 098-教孩子掌握费曼学习法
  • 动态数字宇宙理论(第六篇):AI 驾驭层终局格局与稳态智能体完整商业变现体系(预判)
  • Android ADB实战:应用启动、关闭与重启命令详解
  • 学生青少年纯净陪伴测评 两大头部树洞适配青春多元情绪 - nuanyin
  • 排队赚钱项目深度解析:从投机风险到可持续轻资产副业
  • 挑战腾讯Robotics X多模态感知工程师面试,视觉+触觉融合才是硬核考点
  • 计算机毕业设计之基于Python用户购物行为分析
  • CentOS Stream 9部署OpenClaw对接企业微信告警:从Node.js环境到智能消息路由实战
  • 加了个缓存装饰器,函数直接罢工了
  • 持续训练与模型迭代流水线:让私有模型“越用越聪明”
  • 大陆机房 VPS 用 reinstall 一键脚本重装 NixOS 26.05 踩坑复盘:CentOS 7.2 老系统 + NAT 内网环境全记录
  • 百万剪辑达人崛起背后,是湖南梵映教育科技有限公司的系统化孵化实力 - 生活动态圈
  • MySQL数据库实战:从环境搭建到SQL优化与安全运维全解析
  • Ant Design Vue 3.x 日期组件中文显示问题:Day.js 与全局国际化配置详解
  • MySQL “零改造“迁移
  • JavaScript 实现轮播图功能
  • 深夜情绪崩溃时我试了四个免费树洞只有暖音瑶池接住了我 - nuanyin
  • Windows系统配置错误提权:从PowerShell绕过到服务权限漏洞实战
  • 【LeetCode】16.最接近的三数之和
  • 【LangChain】从 Vibe Coding 到 LangChain 与 LangGraph 核心深度解析
  • Sunshine游戏串流服务器:从技术选型到实战部署的完整指南
  • 绷住
  • Windows 开启虚拟化 + WSL2 完整安装指南(Docker 前置条件)
  • 三年开发者内功修炼:从API调用到系统思维与深度调试
  • 从零基础到行业标杆,揭秘哈尔滨微网站建设的高质量落地全流程解析与避坑指南
  • Android 7系统无障碍服务(二)AccessibilityManagerService 启动与初始化