题目描述:
LeetCode 847. Shortest Path Visiting All Nodes
An undirected, connected graph of N nodes (labeled 0, 1, 2, ..., N-1
) is given as graph
.
graph.length = N
, and j != i
is in the list graph[i]
exactly once, if and only if nodes i
and j
are connected.
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: [[1,2,3],[0],[0],[0]] Output: 4 Explanation: One possible path is [1,0,2,0,3]
Example 2:
Input: [[1],[0,2,4],[1,3,4],[2],[1,2]] Output: 4 Explanation: One possible path is [0,1,4,2,3]
Note:
1 <= graph.length <= 12
0 <= graph[i].length < graph.length
题目大意:
给定无向图graph,求可以遍历所有点的最短路径
解题思路:
Floyd + 动态规划(Dynamic Programming)
时间复杂度 O(2^n * n^2)
利用Floyd求出每对顶点i, j之间的最短距离,记为dp[i][j],代价为O(N^3) 利用status[s][i]记录:状态为s,当前所在节点为i时的最小路径长度 状态s是二进制,表示各节点是否被访问过,1表示已访问,0表示未访问 状态转移方程: status[ns][j] = min(status[ns][j], status[s][i] + dp[i][j]) 其中ns表示从状态s的i点出发到达j点时的新状态
Python代码:
class Solution(object):
def shortestPathLength(self, graph):
"""
:type graph: List[List[int]]
:rtype: int
"""
INF = 0x7FFFFFFF
N = len(graph)
dp = [[INF] * N for x in range(N)]
for i, e in enumerate(graph):
dp[i][i] = 0
for j in e:
dp[i][j] = dp[j][i] = 1
for z in range(N):
for x in range(N):
for y in range(N):
dp[x][y] = min(dp[x][y], dp[x][z] + dp[z][y])
status = {(0, i) : 0 for i in range(N)}
for s in range(1 << N):
for i in range(N):
if (s, i) not in status: continue
v = status[(s, i)]
for j in range(N):
ns = s | (1 << j)
if status.get((ns, j), INF) > v + dp[i][j]:
status[(ns, j)] = v + dp[i][j]
return min(status[((1 << N) - 1, i)] for i in range(N))
比赛时只想到了Floyd + DFS + 剪枝的解法
由于该解法的时间复杂度为O(N!),因此TLE
Python代码:
class Solution(object):
def shortestPathLength(self, graph):
"""
:type graph: List[List[int]]
:rtype: int
"""
INF = 0x7FFFFFFF
N = len(graph)
dp = [[INF] * N for x in range(N)]
for i, e in enumerate(graph):
dp[i][i] = 0
for j in e:
dp[i][j] = dp[j][i] = 1
for z in range(N):
for x in range(N):
for y in range(N):
dp[x][y] = min(dp[x][y], dp[x][z] + dp[z][y])
self.best = INF
visits = set()
def dfs(s, c, t):
if t >= self.best: return
if c == N:
self.best = min(self.best, t)
return
for n in range(N):
if n in visits: continue
visits.add(n)
dfs(n, c + 1, t + dp[s][n])
visits.remove(n)
for n in range(len(graph)):
visits.add(n)
dfs(n, 1, 0)
visits.remove(n)
return self.best
本文链接:http://bookshadow.com/weblog/2018/06/03/leetcode-shortest-path-visiting-all-nodes/
请尊重作者的劳动成果,转载请注明出处!书影博客保留对文章的所有权利。