题目描述
思路
抓住与的特性,一个数无论和谁进行与运算,只能是越与越小。所以:
-
如果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 ]