leetcode 847. 访问所有节点的最短路径 BFS+位运算

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Viscu/article/details/82534299

给出 graph 为有 N 个节点(编号为 0, 1, 2, …, N-1)的无向连通图。
graph.length = N,且只有节点 i 和 j 连通时,j != i 在列表 graph[i] 中恰好出现一次。
返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。
示例 1:
输入:[[1,2,3],[0],[0],[0]]
输出:4
解释:一个可能的路径为 [1,0,2,0,3]
示例 2:
输入:[[1],[0,2,4],[1,3,4],[2],[1,2]]
输出:4
解释:一个可能的路径为 [0,1,4,2,3]
提示:
1 <= graph.length <= 12
0 <= graph[i].length < graph.length

这道题和那道找钥匙的其实都是差不多的,一样的思路。
我们把每隔节点设置为1个bit,0代表没访问过,1代表已经访问过,那么至多有12bit.
我们先把n个点都加入队列中(可以任意选择开始节点,所以都加进去),并设置vis[i][1<<i]为访问过,这个意思就是
第i个节点一开始已经访问过第i节点。bfs跑一遍即可。
class Solution {
    class Idx{ 
        int pos; //节点的编号 0~N-1
        int vStatus; //当前的状态 表示已经访问过多少节点 eg:0011表示第0节点,第1节点都访问过
        int cnt; //当前的步数
        public Idx(int pos, int vStatus, int cnt) {
            this.pos = pos;
            this.vStatus = vStatus;
            this.cnt = cnt;
        }
    }
    public int shortestPathLength(int[][] graph) {
        int n=graph.length;
        Queue<Idx> queue=new LinkedList<Idx>();
        int res=0;
        for(int i=0;i<n;++i){
            queue.offer(new Idx(i,1<<i,0)); //加入队列中,任意节点都可以成为初始节点
            res|=1<<i; //设置结束状态 样例1四个节点 所以这里是1111
        }
        boolean[][] vis=new boolean[n][res+1];
        for(int i=0;i<n;++i){
            vis[i][1<<i]=true; //从哪里开始,哪里就已经被访问过了
        }
        while (!queue.isEmpty()){
            Idx cur=queue.poll();
            if(cur.vStatus==res){
                return cur.cnt;
            }
            int cState=cur.vStatus;
            for(int next:graph[cur.pos]){
                int nState=cState|1<<next;  //next表示下一个访问节点 
                if(!vis[next][nState]){ //例如现在是在0 可访问{1,2,3} 遍历第一个 那么状态就变成了0011.
                    queue.add(new Idx(next,nState,cur.cnt+1));
                    vis[next][nState]=true;
                }
            }
        }
        return -1;
    }
}

猜你喜欢

转载自blog.csdn.net/Viscu/article/details/82534299