【力扣roadmap】3108. 带权图里旅途的最小代价

23 阅读1分钟

题目描述

image.png

思路

抓住与的特性,一个数无论和谁进行与运算,只能是越与越小。所以:

  • 如果query的a和b不在一个连通块上,直接返回-1

  • 如果query的a和b在一个连通块上,直接返回这个连通块的最小与结果

所谓最小的与结果,就是这个连通块上的所有边的与的结果。换句话说,你遍历的边越多,代价越小。

落实到代码上:

  • 建图。直接用拉链法建图就行了,不用链式前向星了。

  • 你可以编写一个dfs,这个dfs做两件事。

    • 将idx所属的连通块上的所有边全部与起来,然后记录在cc_and这个数组中。
    • 将idx所属的连通块进行一个标记,记录在ids中

你从0~n一个一个节点开始遍历,并且用dfs去遍历连通块,本质上是一个连通块一个连通块进行遍历的。

如果cc_and初始化成空列表,那么cc_and会一个连通块与结果接着一个连通块与结果进行添加。那当前cc_and的长度,其实可以充当当前遍历到的连通块的id,因此有代码ids[idx]=len(cc_and)

代码

class Solution:
    def minimumCost(self, n: int, edges: List[List[int]], query: List[List[int]]) -> List[int]:
        ids = [-1] * n 
        cc_and = []
        g = [[] for _ in range(n)]
        for a , b , w in edges:
            g[a].append([b,w])
            g[b].append([a,w]) 
        def dfs(idx):
            ret = -1 
            ids[idx] = len(cc_and)
            for b , w in g[idx] :
                ret &= w 
                if ids[b] < 0 :
                    ret &=  dfs(b) 
            return ret 
        for i in range(n) :
            if ids[i] < 0 : # i没被遍历过
                cc_and.append(dfs(i))
        return   [cc_and[ids[a]]  if ids[a] == ids[b]  else -1  for a , b in query ]