You have an undirected, connected graph of n nodes labeled from 0 to n - 1. You are given an array graph where graph[i] is a list of all the nodes connected with node i by an edge.
Return the length of the shortest path that visits every node. You may start and stop at any node, you may revisit nodes multiple times, and you may reuse edges.
Example 1:
Input: graph = [[1,2,3],[0],[0],[0]]
Output: 4
Explanation: One possible path is [1,0,2,0,3]
Example 2:
Input: graph = [[1],[0,2,4],[1,3,4],[2],[1,2]]
Output: 4
Explanation: One possible path is [0,1,4,2,3]
Constraints:
n == graph.length1 <= n <= 120 <= graph[i].length < ngraph[i]does not containi.- If
graph[a]containsb, thengraph[b]containsa. - The input graph is always connected.
答案
func shortestPathLength(graph [][]int) int {
type Node struct {
//3个属性分别为idx,mask,dist
//mask以位数组代表某个节点是否被访问过,0代表未访问,1代表已访问
id, mask, dist int
}
n := len(graph)
//初始化队列,题目没有要求起点,故每个节点要作为起点算一次
queue := make([]Node, 0, n)
//seen[i][j]记录第i个数,状态j是否被访问过
//同一状态下重复访问某一节点必然是无用功
seen := make([][]bool, n)
//题目不限制起点,所以最开始可以将每个点都存入队列
for i := 0; i < n; i++ {
queue = append(queue, Node{i, 1 << i, 0})
seen[i] = make([]bool, 1<<n)
seen[i][1<<i] = true
}
for len(queue) > 0 {
//出队
now := queue[0]
queue = queue[1:]
//例如图中有 2 个点时,我们分别将 第一个点及其对应的 mask = (01)
//第二个点和其对应的 mask = (10)
//BFS 终点:最终要求所有点均遍历,所以当 mask = 2^n - 1,结束
if now.mask == (1<<n)-1 {
return now.dist
}
for _, neighbor := range graph[now.id] {
nextMask := now.mask | (1 << neighbor)
//如果节点neighbor曾经被以nextMask的状态访问过
//那么再次去访问节点neighbor,使图的遍历状态为nextMask
//肯定也是无用功的
if !seen[neighbor][nextMask] {
queue = append(queue,
Node{id: neighbor,
mask: nextMask,
dist: now.dist + 1,
})
seen[neighbor][nextMask] = true
}
}
}
//never
return -1
}