LeetCode-847. 访问所有节点的最短路径
存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号。
给你一个数组 graph 表示这个图。其中,graph[i] 是一个列表,由所有与节点 i 直接相连的节点组成。
返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。
说实话,困难题,直接看的题解
思路:用一个三元组(u,mask,disk)存放当前结点的序号、结点经过情况和到当前结点经过的距离,mask是用二进制表示,第1个结点000000001,第3个结点00000100,等等类推,当mask变为11111111,也就是2的n次减1,那么所有结点访问完成
再用一个字典(v,mask_v)存放当前结点的序号和结点经过的情况,防止重复搜索该路线
class Solution:
def shortestPathLength(self, graph: List[List[int]]) -> int:
n = len(graph)
# 初始化三元组和字典
q = deque((i, 1<<i, 0) for i in range(n))
seen = {(i, 1<<i) for i in range(n)}
ans = 0
while q:
# 取出三元组的第一个元组
u, mask, disk = q.popleft()
# 如果mask等于2的n次减1,那么所有结点都访问过,输出ans
if mask == (1<<n) - 1:
ans = disk
break
# 搜索相邻的结点
for v in graph[u]:
# 相邻的结点的mask_v变为mask | (1<<v),也就是当前的结点经过情况包括了mask,v
mask_v = mask | (1<<v)
# 如果当前结点经过情况mask_v没有在seen里面,说明这种情况没有发生,那么更新seen,同时q队列增加情况,当前经过结点的距离加1
if (v, mask_v) not in seen:
seen.add((v, mask_v))
q.append((v, mask_v, disk+1))
return ans