第十六章 秘境探索:最小生成树
上古秘境开启,林玄发现需要构建"灵脉网络"连接所有遗迹。石碑提示:“以最小代价连通所有节点,可得传承”。
生成树算法
# Prim算法
def prim_mst(graph):
mst = defaultdict(set)
visited = set()
start_node = next(iter(graph.adj))
visited.add(start_node)
edges = [
(weight, start_node, neighbor)
for neighbor, weight in graph.adj[start_node]
]
heapq.heapify(edges)
while edges:
weight, u, v = heapq.heappop(edges)
if v not in visited:
visited.add(v)
mst[u].add((v, weight))
for neighbor, w in graph.adj[v]:
if neighbor not in visited:
heapq.heappush(edges, (w, v, neighbor))
return mst
# Kruskal算法
def kruskal_mst(graph):
parent = {}
def find(u):
while parent[u] != u:
parent[u] = parent[parent[u]]
u = parent[u]
return u
mst = defaultdict(set)
edges = []
for u in graph.adj:
parent[u] = u
for v, weight in graph.adj[u]:
edges.append((weight, u, v))
edges.sort()
for weight, u, v in edges:
root_u = find(u)
root_v = find(v)
if root_u != root_v:
mst[u].add((v, weight))
parent[root_v] = root_u
return mst
【算法对比】
-
Prim:
- 基于顶点构建
- 适合稠密图
- 时间复杂度O(ElogV)
-
Kruskal:
- 基于边构建
- 适合稀疏图
- 时间复杂度O(ElogE)
秘境挑战
- 构建最优灵脉网络:
def build_spirit_network(graph):
return prim_mst(graph)
- 计算最小灵石消耗:
def calculate_min_cost(mst):
total = 0
for u in mst:
for v, weight in mst[u]:
total += weight
return total // 2 # 每条边被计算两次
- 关键灵脉识别(割边检测):
def find_critical_edges(graph):
# 使用Tarjan算法
pass
- 冗余灵脉检测(环检测):
def detect_redundant_edges(graph):
# 使用并查集
pass