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

Kimi LeetCode 3559. 给边赋权值的方案数 II Go实现

根据题目描述和参考解法,以下是 LeetCode 3559. 给边赋权值的方案数 II 的 Go 实现。

解题思路

核心观察:每条边只能赋权值 1 或 2。
- 权值为 1 的边对路径代价贡献奇数(1)
- 权值为 2 的边对路径代价贡献偶数(2)

设路径上有 `d` 条边,要使总代价为奇数,需要选择奇数条边赋值为 1(其余赋值为 2)。

对于 `d` 条边,选奇数个赋值为 1 的方案数 = 2^{d-1}。

因此问题转化为:对每次查询,求两点之间路径上的边数 `d`,答案为 2^{d-1} \bmod (10^9+7)。当 u=v 时,答案为 0。

求路径边数:使用 LCA(最近公共祖先)算法,路径边数 d = depth[u] + depth[v] - 2 \times depth[lca]。

Go 实现

```go
package main

import (
"math"
)

func assignEdgeWeights(edges [][]int, queries [][]int) []int {
const MOD int = 1_000_000_007
n := len(edges) + 1
LOG := int(math.Ceil(math.Log2(float64(n)))) + 1

// 建图
graph := make([][]int, n+1)
for _, e := range edges {
u, v := e[0], e[1]
graph[u] = append(graph[u], v)
graph[v] = append(graph[v], u)
}

// depth[u]: 节点u到根节点1的深度(边数)
depth := make([]int, n+1)
// parent[k][u]: 节点u的2^k级祖先
parent := make([][]int, LOG)
for i := range parent {
parent[i] = make([]int, n+1)
for j := range parent[i] {
parent[i][j] = -1
}
}

// DFS预处理深度和一级祖先
var dfs func(u, p int)
dfs = func(u, p int) {
parent[0][u] = p
for _, v := range graph[u] {
if v != p {
depth[v] = depth[u] + 1
dfs(v, u)
}
}
}
dfs(1, -1)

// 倍增预处理各级祖先
for k := 1; k < LOG; k++ {
for v := 1; v <= n; v++ {
if parent[k-1][v] != -1 {
parent[k][v] = parent[k-1][parent[k-1][v]]
}
}
}

// LCA查询
lca := func(u, v int) int {
if depth[u] < depth[v] {
u, v = v, u
}
// 将u提升到与v同一深度
for k := LOG - 1; k >= 0; k-- {
if parent[k][u] != -1 && depth[parent[k][u]] >= depth[v] {
u = parent[k][u]
}
}
if u == v {
return u
}
// 同时向上提升u和v
for k := LOG - 1; k >= 0; k-- {
if parent[k][u] != -1 && parent[k][u] != parent[k][v] {
u = parent[k][u]
v = parent[k][v]
}
}
return parent[0][u]
}

// 快速幂
modPow := func(x, n int) int {
res := 1
x = x % MOD
for n > 0 {
if n&1 == 1 {
res = res * x % MOD
}
x = x * x % MOD
n >>= 1
}
return res
}

ans := make([]int, len(queries))
for i, q := range queries {
u, v := q[0], q[1]
if u == v {
ans[i] = 0
continue
}
a := lca(u, v)
d := depth[u] + depth[v] - 2*depth[a] // 路径边数
ans[i] = modPow(2, d-1)
}
return ans
}
```

复杂度分析

- 时间复杂度:O(n \log n + q \log n),其中预处理 DFS 和倍增为 O(n \log n),每次查询 LCA 为 O(\log n)。
- 空间复杂度:O(n \log n),用于存储倍增表。

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

相关文章:

  • 2026黄梅黄金回收避坑指南|30年本土老店全域免费上门,无套路零扣费 - 华金汇黄金回收
  • 运动出汗多穿什么T恤?吸湿排汗的品牌推荐 - 资讯焦点
  • 2026年7月最新亨得利官方服务项目及价格查询|详细维修地址与电话权威信息公告 - 亨得利官方
  • GPT-5.6 API实战指南:特性解析与编程应用优化
  • 石家庄搬家空调移机怎么安排?2026年空调移机专业服务推荐 - 本地品牌推荐
  • 函数式编程—Stream流概述
  • OpenVINO插件系统详解:auto-batch、hetero、intel-cpu等插件在openEuler上的应用
  • 劳力士中国官方售后服务中心|地址及官方客服服务电话权威信息通告(2026年7月更新) - 劳力士服务中心
  • 宇舶中国官方售后服务中心|服务热线及门店详细地址权威信息通知(2026年7月更新) - 亨得利官方服务中心
  • 【C++】类和对象--构造函数进阶(初始化列表与explicit)
  • AI辅助开发生态全景:从方法论到工具链的完整图景
  • 真力时售后维修电话,为您提供专业腕表保养与故障修复服务权威公示(2026年7月最新) - 亨得利官方服务中心
  • Toon Boom Harmony 高效工作流:从节点视图到镜头标记的实战技巧
  • 2026 年当下,诚信的G652D光纤厂家哪个好,揭秘!这根光纤如何让G652D性能暴涨? - 品质体验官
  • 2026麻城黄金回收正规渠道推荐|30年本土老店全域免费上门无套路 - 华金汇黄金回收
  • 医院智能药房实战:C#上位机对接Modbus TCP实现药品库存精准管理
  • Python数据清洗中Lambda函数的实战应用与避坑指南
  • S32DS S32K144 入门实战1——GPIO驱动RGB LED流水灯
  • 浪琴中国官方售后服务中心|全部网点地址及24小时热线权威信息通知(2026年7月更新) - 浪琴服务中心
  • 生产级 RAG 结果不准别乱换模型:零代码调 3 个重排序参数提 22% 准确率附对照表
  • YOLOv11训练时Mosaic与MixUp增强的参数调优:何时开启、何时关闭?
  • MSP430FR235x中断与系统模块实战:从向量表到低功耗设计
  • pandas多维聚合生产实践:滚动窗口、宽表生成与业务可解释性
  • 2026御网杯网络安全赛线下题解(部分)
  • 2026实力之选:铭嘉源装饰公司——常州装修市场的专业服务品牌 - 企业推荐官【官方】
  • Anthropic的研究撕开了AI对齐的底裤-龍德明宇
  • 2026年7月最新烟台江诗丹顿官方售后客服电话及服务网点地址查询 - 江诗丹顿官方服务中心
  • Sqribble文档自动化原理:模板驱动的结构化排版系统
  • 欧米茄中国官方售后服务中心|电话和完整地址权威信息声明(2026年7月最新) - 欧米茄服务中心
  • Axios POST请求传参实战:从基础到高级场景全解析