多源多汇的最短路问题

Leetcode847.访问所有节点最短路径

题目:

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

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

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

提示:

        \quad\quad n==graph.length
        1 <= n <= 12
        ​​​​​​​0 <= graph[i].length < n
        ​​​​​​​graph[i]不包含i
        如果graph[a]包含b ,那么graph[b]也包含a
        输入的图总是连通图

思路:

这是一个多源多汇的最短路问题,可以从任一个节点出发,在任意一个节点结束,只需要满足到达过所有的节点。观察数据可以发现可以使用二进制数来表示到达过的节点状态,例如00001就表示到达过节点0。由此可以想到使用状态压缩DP来解决问题:f[i][j]表示此时的节点状态是i,此时所在的节点是j。由于是无权网络,所以状态转移是f[x][y]=min(f[x][y],f[i][j]+1),其中y是节点j的邻节点(使用BFS解决),x=i|1<<y​​​​​​​表示若i状态包含y,那么x=i,否则x=i+(1<<y)。综上,本题是一个状态压缩DP+BFS问题。

代码:

class Solution {
    class Pair {
        int x,y;
        public Pair(int x,int y) {
            this.x = x;
            this.y = y;
        }
    }

    public int shortestPathLength(int[][] graph) {
        int n = graph.length,INF = (int)1e8;
        int[][] f = new int[1<<n][n];
        Queue<Pair> q = new LinkedList<>();
        //初始化:多源多汇问题
        for(int i = 0 ;i < 1 << n;i++) {
            Arrays.fill(f[i],INF);
        }
        for(int i = 0;i < n;i++) {
            int a = 1 << i;
            f[a][i] = 0;
            q.offer(new Pair(a,i));
        }
        while(q.size() > 0) {
            Pair p = q.poll();
            int i = p.x,j = p.y;
            for(int y : graph[j]) {
                int x = i | 1 << y;
                if(f[x][y] > f[i][j] + 1) {
                    f[x][y] = f[i][j] + 1;
                    q.offer(new Pair(x,y));
                }
            }
        }
        int res = INF;
        for(int i = 0;i < n;i++) {
            res = Math.min(res,f[(1<<n) - 1][i]);
        }
        return res;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值