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

posted @ 2021-08-06 10:48  小Aer  阅读(6)  评论(0编辑  收藏  举报  来源