前序知识:
(1)并查集:
Note:
1.find 目的找到元素的老大 (链表遍历逐层向上找)
2.merge 合并集合(实质改变集合老大,链表性质)
树:
最小生成树:
求最小路径和(Kruskal算法):
(1)再畅通工程(最小生成树)-CSDN博客(空白图)
Note: 先排序结点距离,从小到大利用并查集找结点老大,取较小序号结点作为两结点老大
function KruskalMST(Graph):
# 初始化化并查集(老大设为自己)
# 边按权重从小到大排序
从小到大利用并查集找结点老大,取较小序号结点作为两结点老大
for each edge in Graph.edges:
如果属于同一个集合,跳过这条边(添加这条边会形成环)。
if ds.find_set(edge.node1) != ds.find_set(edge.node2):
MST.append(edge)
ds.union(edge.node1, edge.node2)
如果最小生成树中的边数等于节点数减一,则停止添加边。
if length(MST) == length(Graph.nodes) - 1:
break
return MST
(2)继续畅通工程(最小生成树+并查集)-CSDN博客(有部分边存在)
Note: 一旦路径已建好,将其长度值赋值为0,然后所有路径一致看待
function KruskalMST(Graph):
# 初始化化并查集(老大设为自己)
# 输出结点距离,判断是否存在,若存在,距离赋值为0
# 边按权重从小到大排序
从小到大利用并查集找结点老大,取较小序号结点作为两结点老大
for each edge in Graph.edges:
如果属于同一个集合,跳过这条边(添加这条边会形成环)。
if ds.find_set(edge.node1) != ds.find_set(edge.node2):
MST.append(edge)
ds.union(edge.node1, edge.node2)
如果最小生成树中的边数等于节点数减一,则停止添加边。
if length(MST) == length(Graph.nodes) - 1:
break
return MST
(3)问题 Q: 小希的迷宫(并查集+最小生成树)-CSDN博客(知所有边,判断是否成环,同老大)
Note: 给出相应图路径,
function init(n):
for i = 1 to n:
parent[i] = i # 每个节点的父节点初始化为自己
# 判断是否同集合的数据再次出现,否则dec=0输出No
rootX = find(x),rootY = find(y)
if rootX != rootY:
if rank[rootX] > rank[rootY]:
parent[rootY] = rootX
elif rank[rootX] < rank[rootY]:
parent[rootX] = rootY
else:
dec=0
# 判断所有结点老大是否相同,否则输出No
for i = 1 to n:
if dec1 ==1:
if find(i) != i
unique_leader=find(i)
dec1=0;
else:
if find(i) != unique_leader:
dec=0
图:
最短路径:
(1)最短路径---Dijkstra算法及 变式题(一个人的旅行)-CSDN博客
Note: 不断运行广度优先算法找可见点,计算并更新可见点到源点的最短距离长度
function dijkstra(Graph, source):
dist[] = ∞ for all vertices
prev[] = undefined for all vertices
dist[source] = 0
priority_queue = new MinHeap()
priority_queue.insert(source, 0)
while not priority_queue.isEmpty():
u = priority_queue.extractMin()
for each neighbor v of u:
alt = dist[u] + weight(u, v)
if alt < dist[v]:
dist[v] = alt
prev[v] = u
priority_queue.decreaseKey(v, alt)
return dist, prev