图论中的最小高度生成树问题
字数 1077 2025-11-07 12:32:50
图论中的最小高度生成树问题
题目描述
给定一个无向连通图G=(V,E),我们需要找到一棵生成树T,使得T的高度最小。生成树的高度定义为从根节点到最远叶节点的路径长度(边数)。最小高度生成树问题就是要找到所有生成树中高度最小的那棵树。
问题分析
- 这是一个优化问题,需要在所有生成树中找到高度最小的解
- 高度与树的直径密切相关,最小高度生成树实际上就是最小直径生成树
- 问题的关键在于找到图的"中心"节点作为根
基本概念
- 图的中心:图中偏心率最小的节点(偏心率是节点到其他所有节点的最大距离)
- 图的半径:所有节点偏心率的最小值
- 图的直径:所有节点偏心率的最大值
解题步骤
步骤1:理解问题本质
最小高度生成树的高度等于图的半径。我们需要:
- 找到图的所有中心节点
- 以中心节点为根构建BFS树
步骤2:计算所有节点对的最短路径
使用Floyd-Warshall算法或多次BFS计算所有节点对之间的距离:
- 对于每个节点v,执行BFS得到到其他所有节点的距离
- 构建距离矩阵D,其中D[i][j]表示节点i到j的最短距离
步骤3:计算每个节点的偏心率
对于每个节点v,其偏心率ecc(v) = max{D[v][u] | u ∈ V}
即节点v到其他所有节点的最大距离
步骤4:找到图的中心
图的半径radius = min{ecc(v) | v ∈ V}
中心节点集合C = {v ∈ V | ecc(v) = radius}
步骤5:构建最小高度生成树
从任意中心节点c ∈ C开始:
- 以c为根节点执行BFS
- BFS过程中记录每个节点的父节点
- 用所有(u, parent[u])边构建生成树
算法实现细节
距离计算优化
def compute_eccentricities(graph):
n = len(graph)
eccentricities = [0] * n
for i in range(n):
# BFS从节点i开始
dist = [-1] * n
dist[i] = 0
queue = deque([i])
while queue:
u = queue.popleft()
for v in graph[u]:
if dist[v] == -1:
dist[v] = dist[u] + 1
queue.append(v)
eccentricities[i] = max(dist)
return eccentricities
构建最小高度生成树
def build_min_height_spanning_tree(graph, center):
n = len(graph)
parent = [-1] * n
visited = [False] * n
queue = deque([center])
visited[center] = True
tree_edges = []
while queue:
u = queue.popleft()
for v in graph[u]:
if not visited[v]:
visited[v] = True
parent[v] = u
tree_edges.append((u, v))
queue.append(v)
return tree_edges
时间复杂度分析
- 计算偏心率:O(|V|(|V|+|E|))
- 找到中心节点:O(|V|)
- 构建生成树:O(|V|+|E|)
- 总时间复杂度:O(|V|(|V|+|E|))
实例演示
考虑一个6个节点的图:
0-1-2-4
| |
3 5
-
计算各节点偏心率:
- ecc(0)=3, ecc(1)=2, ecc(2)=2
- ecc(3)=3, ecc(4)=3, ecc(5)=3
-
中心节点:节点1和2(偏心率=2)
-
以节点1为根构建BFS树:
- 层级0: 节点1
- 层级1: 节点0, 2
- 层级2: 节点3, 4, 5
-
生成树高度为2,是最小可能高度
关键洞察
- 最小高度生成树的高度等于图的半径
- 中心节点是构建最小高度生成树的最佳根节点
- 通过BFS可以高效构建这样的生成树
这个算法保证了找到的生成树具有最小可能的高度,是解决该问题的经典方法。