2026-07-19:增量偶权环查询。用go语言,有一个包含 n 个节点的无向图,节点编号从 0 到 n-1,初始时图中不存在任何边。现在给定一个边序列 edges,其中每个元素都表示一条边,包含两个

发布时间:2026/7/19 13:24:34

2026-07-19:增量偶权环查询。用go语言,有一个包含 n 个节点的无向图,节点编号从 0 到 n-1,初始时图中不存在任何边。现在给定一个边序列 edges,其中每个元素都表示一条边,包含两个
2026-07-19增量偶权环查询。用go语言有一个包含 n 个节点的无向图节点编号从 0 到 n-1初始时图中不存在任何边。现在给定一个边序列 edges其中每个元素都表示一条边包含两个端点和一个权重权重的取值只能是 0 或 1。你需要按照这个序列的顺序逐条处理边对于当前这条边判断如果将其加入当前图中是否会导致出现某个环的边权重之和为奇数。只有当所有环的边权和都是偶数时才真正把这条边加入图中否则就忽略它。最终统计并返回按照此规则成功添加到图中的边的总数。3 n 50000。1 edges.length 50000。edges[i] [ui, vi, wi]。0 ui vi n。所有边都是唯一的。wi 0 或 wi 1。输入 n 3, edges [[0,1,1],[1,2,1],[0,2,1]]。输出 2。解释[0, 1, 1]添加节点 0 和节点 1 之间的边权重为 1。[1, 2, 1]添加节点 1 和节点 2 之间的边权重为 1。[0, 2, 1]节点 0 和节点 2 之间的边图中的虚线不被添加因为环 0 - 1 - 2 - 0 的边权和为 1 1 1 3奇数。题目来自力扣3887。大体步骤如下步骤 1问题转化与数据结构初始化转化判定条件边权为 0 或 1因此一个环的边权和为偶数 (\Longleftrightarrow) 环上所有边权的异或和为 0。如果图中所有环的异或和都为 0那么图中任意两个节点之间的任意路径的异或和都是唯一确定的与路径无关。这个性质正是我们维护的目标。设计并查集使用一个带权并查集包含两个长度为 (n) 的数组fa[x]节点 (x) 的父节点初始时每个节点的父节点都是自己。dis[x]从节点 (x) 到其父节点fa[x]的路径上的边权异或和。初始时所有dis[x] 0。当并查集中一棵树被维护好时对任意节点 (x)我们可以通过不断向上查找根同时累积dis值得到 (x) 到整棵树根节点的异或距离。步骤 2定义带路径压缩的find操作递归查找根节点对于节点 (x)如果fa[x] ! x说明它不是根先递归地找到fa[x]的根节点root。更新异或距离路径压缩在递归返回时已知fa[x]到root的异或距离已经更新好即dis[fa[x]]表示fa[x]到root的异或和。我们希望把 (x) 直接连到root上那么新的dis[x]应该是 (x) 到旧父节点fa[x]的异或和再异或上fa[x]到root的异或和。因此执行dis[x] dis[x] ^ dis[fa[x]]然后将fa[x]设为root。返回根节点返回root。这样经过find(x)后fa[x]直接指向根且dis[x]成为 (x) 到根的异或距离。步骤 3定义merge操作以处理一条边输入一条边(from, to, value)其中value是边权0 或 1。我们要判断这条边能否加入。查找两端所在根及异或距离令x find(from)y find(to)。此时dis[from]是from到根x的异或距离。dis[to]是to到根y的异或距离。情况 A两端已在同一连通块x y此时from与to之间已存在一条路径该路径的异或和为dis[from] ^ dis[to]。如果加入当前边会形成一个新环环的异或和为(dis[from] ^ dis[to]) ^ value要使得环的边权和为偶数必须满足异或和为 0即dis[from] ^ dis[to] value若相等说明加入后不会产生奇权环接受该边返回true但图结构不变因为已经在同一连通块中无需再连边。若不等说明会产生奇权环拒绝该边返回false不修改图。情况 B两端不在同一连通块x ! y此时加入这条边不会形成任何环因为原本不连通所以一定满足“所有环边权和为偶数”的条件我们接受该边并需要将两棵树合并。合并时我们要为新的连接关系设置dis值使得从from到to的异或距离等于value。设我们要将根x接到根y上即设置fa[x] y。那么需要确定dis[x]从x到y的边权异或值使得路径from → x → y → to的总异或和等于value。这个路径的异或和为dis[from] ^ dis[x] ^ dis[to]。令其等于valuedis[from] ^ dis[x] ^ dis[to] value解得dis[x] value ^ dis[from] ^ dis[to]。执行赋值完成合并返回true。步骤 4主流程依次处理所有边初始化并查集ans 0。遍历边列表edges对每条边调用merge(from, to, weight)。如果merge返回true则ans加一。遍历结束后ans即为成功添加到图中的边的总数。步骤 5示例验证n3, edges[[0,1,1],[1,2,1],[0,2,1]]初始节点 0,1,2 各自独立。边 [0,1,1]find(0)0, find(1)1不同根合并。dis[0] 1 ^ 0 ^ 0 1fa[0]1。加入成功ans1。边 [1,2,1]find(1)1, find(2)2不同根合并。dis[1] 1 ^ 0 ^ 0 1fa[1]2。此时dis[0]经过find压缩后会是dis[0]^dis[1]1^10即 0 到根 2 的异或距离为 0。加入成功ans2。边 [0,2,1]find(0)2, dis[0]0find(2)2, dis[2]0。同根检查dis[0] ^ dis[2] 0是否等于 10 ! 1产生奇权环拒绝。最终ans2。复杂度分析时间复杂度并查集使用了路径压缩find和merge操作的均摊时间复杂度几乎是常数级别精确地说是反阿克曼函数 (O(\alpha(n)))。主循环处理 (m) 条边每条边执行常数次find和简单运算因此总时间复杂度为 (O(m \cdot \alpha(n)))。在数据范围内(n, m \leq 50000)这非常高效。额外空间复杂度除了输入和少量变量外我们维护了两个大小为 (n) 的数组fa和dis所以额外空间复杂度为 (O(n))。Go完整代码如下packagemainimport(fmt)typeunionFindstruct{fa[]int// fa[x] 是 x 的代表元dis[]int// dis[x] 从 x 到 fa[x] 的路径异或和}funcnewUnionFind(nint)unionFind{fa:make([]int,n)dis:make([]int,n)fori:rangefa{fa[i]i}returnunionFind{fa,dis}}func(u unionFind)find(xint)int{ifu.fa[x]!x{root:u.find(u.fa[x])u.dis[x]^u.dis[u.fa[x]]u.fa[x]root}returnu.fa[x]}func(u unionFind)merge(from,to,valueint)bool{x,y:u.find(from),u.find(to)ifxy{returnu.dis[from]^u.dis[to]value}u.dis[x]value^u.dis[to]^u.dis[from]u.fa[x]yreturntrue}funcnumberOfEdgesAdded(nint,edges[][]int)(ansint){uf:newUnionFind(n)for_,e:rangeedges{ifuf.merge(e[0],e[1],e[2]){ans}}return}funcmain(){n:3edges:[][]int{{0,1,1},{1,2,1},{0,2,1}}result:numberOfEdgesAdded(n,edges)fmt.Println(result)}Python完整代码如下# -*-coding:utf-8-*-classUnionFind:def__init__(self,n:int):self.falist(range(n))# 父节点代表元self.dis[0]*n# 到父节点的路径异或和deffind(self,x:int)-int:ifself.fa[x]!x:rootself.find(self.fa[x])self.dis[x]^self.dis[self.fa[x]]self.fa[x]rootreturnself.fa[x]defmerge(self,u:int,v:int,w:int)-bool: 尝试加入权重为 w 的边 (u, v)。 若不会产生奇数环即异或条件满足则真正合并并返回 True 否则返回 False。 x,yself.find(u),self.find(v)ifxy:# 已连通检查当前路径异或和是否等于 wreturnself.dis[u]^self.dis[v]w# 未连通合并两个集合self.dis[x]w^self.dis[u]^self.dis[v]self.fa[x]yreturnTruedefnumberOfEdgesAdded(n:int,edges:list[list[int]])-int:ufUnionFind(n)ans0foru,v,winedges:ifuf.merge(u,v,w):ans1returnansif__name____main__:n3edges[[0,1,1],[1,2,1],[0,2,1]]print(numberOfEdgesAdded(n,edges))C完整代码如下#includeiostream#includevectorusingnamespacestd;classUnionFind{public:vectorintfa;// 父节点代表元vectorintdis;// 到父节点的路径异或和UnionFind(intn):fa(n),dis(n,0){for(inti0;in;i){fa[i]i;}}intfind(intx){if(fa[x]!x){introotfind(fa[x]);dis[x]^dis[fa[x]];fa[x]root;}returnfa[x];}// 尝试加入权值为 w 的边 (u, v)// 返回 true 表示加入后无矛盾false 表示会产生奇数环矛盾boolmerge(intu,intv,intw){intxfind(u),yfind(v);if(xy){// 已连通检查当前路径异或和是否等于 wreturn(dis[u]^dis[v])w;}// 未连通合并两个集合fa[x]y;dis[x]w^dis[u]^dis[v];returntrue;}};intnumberOfEdgesAdded(intn,constvectorvectorintedges){UnionFinduf(n);intans0;for(constautoe:edges){if(uf.merge(e[0],e[1],e[2])){ans;}}returnans;}intmain(){intn3;vectorvectorintedges{{0,1,1},{1,2,1},{0,2,1}};intresultnumberOfEdgesAdded(n,edges);coutresultendl;return0;}

相关新闻

AI数字人嘴型不同步、口型崩坏、延迟卡顿——硬件适配清单与GPU资源调度公式全公开

AI数字人嘴型不同步、口型崩坏、延迟卡顿——硬件适配清单与GPU资源调度公式全公开

2026/7/19 13:24:34

更多请点击: https://codechina.net 第一章:AI数字人直播带货的核心痛点与技术本质 AI数字人直播带货并非简单地将真人主播替换成3D模型,其背后是多模态感知、实时驱动、语义理解与商业逻辑深度耦合的系统工程。当前行业普遍存在“形似神不似…

AI数字人不是“换脸”!深度拆解12层技术栈:TTS/LLM驱动/VISUAL RENDER/实时推流/多模态对齐全链路图谱

AI数字人不是“换脸”!深度拆解12层技术栈:TTS/LLM驱动/VISUAL RENDER/实时推流/多模态对齐全链路图谱

2026/7/19 13:24:34

更多请点击: https://intelliparadigm.com 第一章:AI数字人不是“换脸”!——虚拟主播的本质认知与技术边界 AI数字人常被误读为“高级换脸工具”,实则其技术内核远超图像替换范畴。它融合语音合成(TTS)、…

我们聊聊AI API网关:当大模型调用变成一场混战

我们聊聊AI API网关:当大模型调用变成一场混战

2026/7/19 13:14:34

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

Unity Profiler避坑指南:打包设置与Deep Profiling实战解析

Unity Profiler避坑指南:打包设置与Deep Profiling实战解析

2026/7/19 20:25:04

1. 项目概述:为什么你需要这份避坑指南? 如果你是一名Unity开发者,无论你是刚入行的新人,还是已经摸爬滚打了几年的老手,我敢打赌,你一定在某个深夜对着Unity Profiler窗口里那些上蹿下跳的彩色线条和神秘数…

PFC+LLC电源EMC整改:从误区到系统方法论

PFC+LLC电源EMC整改:从误区到系统方法论

2026/7/19 20:25:04

EMC整改是每个硬件工程师的必修课,但很多人都在"拆东墙补西墙"的循环中崩溃。今天我们就来系统梳理EMC整改的正确思路,特别是针对常见的PFCLLC电源架构。 1. EMC整改核心误区解析 很多工程师在EMC整改时容易陷入几个典型误区: 误…

AI咨询服务评估指南:四维框架避开陷阱选对合作伙伴

AI咨询服务评估指南:四维框架避开陷阱选对合作伙伴

2026/7/19 20:25:04

AI咨询服务的浪潮正在席卷各行各业,但真正能带来实际价值的机构却凤毛麟角。很多企业投入数十万甚至上百万预算后,得到的往往是一堆华而不实的PPT和无法落地的方案。问题到底出在哪里?本文将从技术可行性、团队实力、案例实效和商业模式四个核…

Unity字体性能优化实战:BMFont位图字体生成与集成指南

Unity字体性能优化实战:BMFont位图字体生成与集成指南

2026/7/19 20:25:04

1. 项目概述:为什么Unity项目需要BMFont字体工具? 如果你在Unity里做过UI,尤其是需要大量中文文本的UI,大概率遇到过字体文件过大、运行时内存占用高、或者在某些设备上字体显示模糊、发虚的问题。这几乎是每个Unity开发者&#x…

MPC-BE播放器:高效解码与多媒体处理全解析

MPC-BE播放器:高效解码与多媒体处理全解析

2026/7/19 20:25:04

1. MPC-BE播放器深度解析MPC-BE(Media Player Classic - Black Edition)作为一款经典多媒体播放器的现代分支,在影音爱好者圈子里一直保持着稳定的用户群体。这个基于原始MPC项目重构的播放器,在保持轻量级特性的同时,…

XR渲染技术核心原理与优化实践

XR渲染技术核心原理与优化实践

2026/7/19 20:15:03

1. XR渲染技术的核心定位与行业现状 XR渲染技术作为扩展现实体验的基础支撑,其本质是通过计算机图形学手段在虚实融合环境中实现视觉内容的高效呈现。与传统的3D渲染不同,XR渲染需要同时解决三个核心矛盾:实时性要求与复杂场景的矛盾、物理空…

微服务进阶:服务网格与Istio

微服务进阶:服务网格与Istio

2026/7/19 0:03:49

541|微服务进阶:服务网格与Istio 上篇文章我们聊了微服务的基本概念和拆分方法。 但微服务多了,问题也多了: 服务之间怎么通信? 怎么监控每个服务的调用链路? 熔断、限流、重试怎么做? 安全认证怎么统一? 以前这些都靠SDK库(比如Hystrix、Feign),每个服务都要集成…

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

2026/7/19 0:03:49

一、零售门店全域协同业务背景与行业痛点 1.1 门店超级终端设备矩阵(连锁便利店/商超标准配置) 自助收银Kiosk一体机:顾客结算、自助核销优惠券、商品素材预览;运营折叠平板:店长后台商品上新、图片录入、活动配置、…

噗叽短视频界面分析

噗叽短视频界面分析

2026/7/19 0:03:49

1 和小红书类似,可以采用类似判断方法------------其实他比小红书好判断,因为他没有图片,控件位置几乎是固定的,都不用判断------------2 因为他没有点赞按钮------------而且几乎所有控件位置都是完全一样的,所以我就…

微服务进阶:服务网格与Istio

微服务进阶:服务网格与Istio

2026/7/19 0:03:49

541|微服务进阶:服务网格与Istio 上篇文章我们聊了微服务的基本概念和拆分方法。 但微服务多了,问题也多了: 服务之间怎么通信? 怎么监控每个服务的调用链路? 熔断、限流、重试怎么做? 安全认证怎么统一? 以前这些都靠SDK库(比如Hystrix、Feign),每个服务都要集成…

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

2026/7/19 0:03:49

一、零售门店全域协同业务背景与行业痛点 1.1 门店超级终端设备矩阵(连锁便利店/商超标准配置) 自助收银Kiosk一体机:顾客结算、自助核销优惠券、商品素材预览;运营折叠平板:店长后台商品上新、图片录入、活动配置、…

噗叽短视频界面分析

噗叽短视频界面分析

2026/7/19 0:03:49

1 和小红书类似,可以采用类似判断方法------------其实他比小红书好判断,因为他没有图片,控件位置几乎是固定的,都不用判断------------2 因为他没有点赞按钮------------而且几乎所有控件位置都是完全一样的,所以我就…