LeetCode 题解工作台

带权图里旅途的最小代价

给你一个 n 个节点的带权无向图,节点编号为 0 到 n - 1 。 给你一个整数 n 和一个数组 edges ,其中 edges[i] = [u i , v i , w i ] 表示节点 u i 和 v i 之间有一条权值为 w i 的无向边。 在图中,一趟旅途包含一系列节点和边。旅途开始和结束点…

category

4

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

困难 · 并查集

bolt

答案摘要

我们注意到,一个正整数与其他若干个正整数不断进行“按位与”运算,结果只会越来越小。因此,为了使得旅途的代价尽可能小,我们应该将处于同一个连通分量的所有边的权值进行“按位与”运算,然后再进行查询。 那么,问题转化为,如何找出同一个连通份量的所有边,然后进行“按位与”运算。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 并查集 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个 n 个节点的带权无向图,节点编号为 0 到 n - 1 。

给你一个整数 n 和一个数组 edges ,其中 edges[i] = [ui, vi, wi] 表示节点 ui 和 vi 之间有一条权值为 wi 的无向边。

在图中,一趟旅途包含一系列节点和边。旅途开始和结束点都是图中的节点,且图中存在连接旅途中相邻节点的边。注意,一趟旅途可能访问同一条边或者同一个节点多次。

如果旅途开始于节点 u ,结束于节点 v ,我们定义这一趟旅途的 代价 是经过的边权按位与 AND 的结果。换句话说,如果经过的边对应的边权为 w0, w1, w2, ..., wk ,那么代价为w0 & w1 & w2 & ... & wk ,其中 & 表示按位与 AND 操作。

给你一个二维数组 query ,其中 query[i] = [si, ti] 。对于每一个查询,你需要找出从节点开始 si ,在节点 ti 处结束的旅途的最小代价。如果不存在这样的旅途,答案为 -1 。

返回数组 answer ,其中 answer[i] 表示对于查询 i 的 最小 旅途代价。

 

示例 1:

输入:n = 5, edges = [[0,1,7],[1,3,7],[1,2,1]], query = [[0,3],[3,4]]

输出:[1,-1]

解释:

第一个查询想要得到代价为 1 的旅途,我们依次访问:0->1(边权为 7 )1->2 (边权为 1 )2->1(边权为 1 )1->3 (边权为 7 )。

第二个查询中,无法从节点 3 到节点 4 ,所以答案为 -1 。

示例 2:

输入:n = 3, edges = [[0,2,7],[0,1,15],[1,2,6],[1,2,1]], query = [[1,2]]

输出:[0]

解释:

第一个查询想要得到代价为 0 的旅途,我们依次访问:1->2(边权为 1 ),2->1(边权 为 6 ),1->2(边权为 1 )。

 

提示:

  • 1 <= n <= 105
  • 0 <= edges.length <= 105
  • edges[i].length == 3
  • 0 <= ui, vi <= n - 1
  • ui != vi
  • 0 <= wi <= 105
  • 1 <= query.length <= 105
  • query[i].length == 2
  • 0 <= si, ti <= n - 1
lightbulb

解题思路

方法一:贪心 + 并查集

我们注意到,一个正整数与其他若干个正整数不断进行“按位与”运算,结果只会越来越小。因此,为了使得旅途的代价尽可能小,我们应该将处于同一个连通分量的所有边的权值进行“按位与”运算,然后再进行查询。

那么,问题转化为,如何找出同一个连通份量的所有边,然后进行“按位与”运算。

我们可以用并查集来维护连通分量。

具体地,我们遍历每一条边 (u,v,w)(u, v, w),将 uuvv 进行合并。然后,我们再一次遍历每一条边 (u,v,w)(u, v, w),找到 uuvv 所在的连通分量的根节点 rootroot,用一个数组 gg 记录每个连通分量的所有边的权值进行“按位与”运算的结果。

最后,对于每一个查询 (s,t)(s, t),我们首先判断 sstt 是否相等,如果相等,那么答案为 00,否则,我们判断 sstt 是否在同一个连通分量中,如果在同一个连通分量中,那么答案为该查询的连通分量的根节点的 gg 值,否则,答案为 1-1

时间复杂度 O((n+m+q)×α(n))O((n + m + q) \times \alpha(n)),空间复杂度 O(n)O(n)。其中 nn, mmqq 分别表示节点数、边数和查询数,而 α(n)\alpha(n) 表示 Ackermann 函数的反函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class UnionFind:
    def __init__(self, n):
        self.p = list(range(n))
        self.size = [1] * n

    def find(self, x):
        if self.p[x] != x:
            self.p[x] = self.find(self.p[x])
        return self.p[x]

    def union(self, a, b):
        pa, pb = self.find(a), self.find(b)
        if pa == pb:
            return False
        if self.size[pa] > self.size[pb]:
            self.p[pb] = pa
            self.size[pa] += self.size[pb]
        else:
            self.p[pa] = pb
            self.size[pb] += self.size[pa]
        return True


class Solution:
    def minimumCost(
        self, n: int, edges: List[List[int]], query: List[List[int]]
    ) -> List[int]:
        g = [-1] * n
        uf = UnionFind(n)
        for u, v, _ in edges:
            uf.union(u, v)
        for u, _, w in edges:
            root = uf.find(u)
            g[root] &= w

        def f(u: int, v: int) -> int:
            if u == v:
                return 0
            a, b = uf.find(u), uf.find(v)
            return g[a] if a == b else -1

        return [f(s, t) for s, t in query]
speed

复杂度分析

指标
时间complexity is O(m + n + q) because each edge and vertex is processed once during DSU merging and bit mask updates, and each query is answered in constant time using precomputed structures. Space complexity is O(n + m) for storing DSU arrays and bit masks.
空间O(n + m)
psychology

面试官常问的追问

外企场景
  • question_mark

    Look for usage of Disjoint Set Union with array indices to represent connected components.

  • question_mark

    Expect candidates to optimize repeated path queries with bit manipulation for fast cost computation.

  • question_mark

    Watch for correct handling of walks that can revisit vertices or edges multiple times.

warning

常见陷阱

外企场景
  • error

    Assuming a walk cannot reuse edges or vertices, leading to incorrect minimum costs.

  • error

    Ignoring cases where nodes are disconnected, producing wrong outputs instead of -1.

  • error

    Overcomplicating propagation without using array plus bit manipulation, causing timeouts on large inputs.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Compute minimum cost walks in directed weighted graphs with array plus bit manipulation for strongly connected components.

  • arrow_right_alt

    Limit walk lengths to k edges and use array-based DP with bit masks to find minimum cost.

  • arrow_right_alt

    Handle dynamic edge insertions or deletions while maintaining minimum cost queries using DSU and bit manipulation.

help

常见问题

外企场景

带权图里旅途的最小代价题解:并查集 | LeetCode #3108 困难