leetcode 847. Shortest Path Visiting All Nodes 无向连通图遍历最短路径
Posted sfzyk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 847. Shortest Path Visiting All Nodes 无向连通图遍历最短路径相关的知识,希望对你有一定的参考价值。
设计最短路径 用bfs 天然带最短路径
每一个状态是 当前的阶段 和已经访问过的节点
下面是正确但是超时的代码
class Solution:
def shortestPathLength(self, graph):
"""
:type graph: List[List[int]]
:rtype: int
"""
N=len(graph)
Q=collections.deque([(1 << x, x) for x in range(N)])
D=collections.defaultdict(lambda:N*N)
for i in range(N):
D[1<<i,i]=0
mask=0
#listr= [i for i in range(N)]
#random.shuffle(listr)
for i in range(N):
mask=mask|1<<i
while Q:
a,h=Q.popleft()
d=D[a,h]
if(a==mask):
return d
for child in graph[h]:
new_a=a |(1<<child)
Q.append((new_a,child))
D[new_a,child]=min(d+1,D[new_a,child])
下面的代码稍微有优化,但是这种优化是非常好的。(值得思考的优化)
归根结底是因为没有考虑好一个状态是指什么。
在这里一个状态指的是, 以前便利过的节点 和 当前的节点。
有了这个节点状态
就不用把(到达这个节点的距离作为节点的一部分加入节点中,加入会引起性能损失)
到达这个节点的距离 单独存入一个数组中做优化 如果同一个状态后来的距离反而更长 那就丢弃。
class Solution:
def shortestPathLength(self, graph):
N=len(graph)
Q=collections.deque([(1 << x, x) for x in range(N)])
D=collections.defaultdict(lambda:N*N)
for i in range(N):
D[1<<i,i]=0
mask=0
for i in range(N):
mask=mask|1<<i
while Q:
cover,head=Q.popleft()
d=D[cover,head]
if(cover==mask):
return d
for child in graph[head]:
new_a=cover |(1<<child)
if(d+1<D[new_a,child]):
D[new_a,child]=d+1
Q.append((new_a,child))
动态规划算法
一个数组
state[ cover ][ head ] 表示当前状态所能达到的最小距离
head 维数的遍历顺序随意
cover 的遍历循序是从小到大
因为 new_cover=cover| child 这样的话内在隐含着一个内在的顺序
这样看来 这个题目有意卡掉了那些没有注意到这种顺序的方法
"relaxation step" (for those familiar with the Bellman-Ford algorithm)
复习 Bellman-Ford algorithm
O(V*E)
1 初始化
2 n-1 次循环 每一个循环遍历每一个边 做 relaxtion step
3 额外判断是否每一条边都 存在优化空间
第i次循环 实际上是在寻找 单源最短路径
如果n-1 次循环后还能做 relaxtion step 那么说明图中存在 负权回路
以上是关于leetcode 847. Shortest Path Visiting All Nodes 无向连通图遍历最短路径的主要内容,如果未能解决你的问题,请参考以下文章
leetcode 847. Shortest Path Visiting All Nodes 无向连通图遍历最短路径
LeetCode - 581. Shortest Unsorted Continuous Subarray