最近在学习dijkstra最短路算法,朴素算法的时间复杂度是O(N^2),也就是说当数据量达到1e5的时候,1S可能就不够了,因此我们需要对算法进行优化,如果能让时间复杂度变为O(NlogN)的话,一般来说能过所有的dijkstra最短路相关的问题,那么我们如何进行优化呢?
我们知道dijkstra算法外面一层循环,里面两个循环,范围都是1~n,外面循环一次就确定一个最短路径的长度,这是不能够去优化的,因此我们想到优化内部的循环。内部算法的目的是找到一个还未被访问,并且单源路径最短的一个点,并且对这个点所能连接到的点的路径进行更新操作。我们看到每次都找出最小值?就可以想到用二叉堆来优化这个问题,算法的时间复杂度是logn,因此我们可以利用二叉堆来优化这个问题。
由于第一次接触二叉堆,我先学习了一下二叉堆的基本知识,并且在洛谷上找到了相应的题目进行训练,这样可以深入理解二叉堆,以下是二叉堆的解题代码,二叉堆优化的dijkstra算法过几天会发出!
AC代码
"""
最小堆的实现
"""
class node:
def __init__(self,val=0,index=0):
node.val=val
node.index=index
global tree
global A,B,C
global n,m
tree=[node() for _ in range(10010)]
A=[0 for _ in range(10010)]
B=[0 for _ in range(10010)]
C=[0 for _ in range(10010)]
F=[1 for _ in range(10010)]
def change(x,y):
t=tree[x].index
tree[x].index=tree[y].index
tree[y].index=t
t=tree[x].val
tree[x].val=tree[y].val
tree[y].val=t
def maintain_heap(idx):
left=2*idx+1
right=2*idx+2
small=0
#找出更小的值
if left<n and tree[left].val<tree[idx].val:
small=left
else:
small=idx
if right<n and tree[right].val<tree[small].val:
small=right
#如果父结点不是最小值 向上更新
if small!=idx:
change(idx,small)
maintain_heap(small)
def built_heap():
#自底向上建堆,确保每一个子堆都是最小堆
for i in range(n//2,-1,-1):
maintain_heap(i)
n,m=map(int,input().split())
coefficient=[[] for i in range(n)]
for i in range(n):
A[i],B[i],C[i]=map(int,input().split())
tree[i].index=i
tree[i].val=A[i]*F[i]**2+B[i]*F[i]+C[i]
built_heap()
for i in range(m):
print(tree[0].val,end=" ")
idx=tree[0].index
F[idx]+=1
tree[0].val=A[idx]*F[idx]**2+B[idx]*F[idx]+C[idx]
maintain_heap(0)
AC截图