Leetcode847.访问所有节点最短路径
题目:
存在一个由个节点组成的无向连通图,图中的节点按从到编号。
给你一个数组表示这个图。其中,是一个列表,由所有与节点直接相连的节点组成。
返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。
提示:
不包含
如果包含 ,那么也包含
输入的图总是连通图
思路:
这是一个多源多汇的最短路问题,可以从任一个节点出发,在任意一个节点结束,只需要满足到达过所有的节点。观察数据可以发现可以使用二进制数来表示到达过的节点状态,例如00001就表示到达过节点0。由此可以想到使用状态压缩DP来解决问题:表示此时的节点状态是,此时所在的节点是。由于是无权网络,所以状态转移是,其中是节点的邻节点(使用BFS解决),表示若状态包含,那么,否则。综上,本题是一个状态压缩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;
}
}