847. 访问所有节点的最短路径

507 阅读1分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

题目

存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号。

给你一个数组 graph 表示这个图。其中,graph[i] 是一个列表,由所有与节点 i 直接相连的节点组成。

返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。

 

示例 1:

image.png

输入:graph = [[1,2,3],[0],[0],[0]] 输出:4 解释:一种可能的路径为 [1,0,2,0,3] 示例 2:

输入:graph = [[1],[0,2,4],[1,3,4],[2],[1,2]] 输出:4 解释:一种可能的路径为 [0,1,4,2,3]

解题思路

  1. 因为这题可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。所以我们不能像普通BFS的使用set进行去重,我们需要使用到达某一节点时路径上经过的节点情况去进行去重
  2. 因为1 <= n <= 12,所以我们只需要使用一个int类型去记录路径下经过的节点
  3. 再使用广度优先搜索,队列中的元素,分别为
  • 当前位于的节点编号;
  • 一个长度为 n 的二进制数,表示每一个节点是否经过。如果第 i 位是 1,则表示节点 i 已经过,否则表示节点 i 未经过;
  • 表示到当前节点为止经过的路径长度。 找出第一条包含所有节点的路径

代码

class Solution {
    public int shortestPathLength(int[][] graph) {

        int n=graph.length;
        boolean[][] check=new boolean[n][1<<n];
        Queue<int[]> queue=new LinkedList<>();
        for (int i = 0; i < n; i++) {
            queue.add(new int[]{i,0,1<<i});
            check[i][1<<i]=true;
        }
        while (!queue.isEmpty())
        {
            int[] cur = queue.poll();
            if ((1<<n)-1==cur[2])
                return cur[1];
            for (int g : graph[cur[0]]) {
                int nx=cur[2]|(1<<g);
                if (!check[g][nx])
                {
                    queue.add(new int[]{g,cur[1]+1,nx});
                    check[g][nx]=true;
                }
            }
        }
        return 0;
    }
}