[图算法系列] —— kruskal

222 阅读1分钟

kruskal是个贪心算法,对于n个节点的图,最小生成树有n-1条边。

初始设所有点为孤立点,我们每次取权值最小的边,如果该边两端点尚未连通,那么该边就是最小生成树的一条边,接着连通两点。

节点是否连通用到了并查集。

root = [i for i in range(n+1)]

def find_root(i, root):
    if root[i] != i:
        root[i] = find_root(root[i], root)
    return root[i]

使用root数组记录节点i的祖先节点,如果两个节点拥有共同的祖先,则说明两节点连通。

# 构造图,使用edges存储所有的边
n, m = list(map(int, input().split()))
edges, mst = [], []
for _ in range(m):
    x, y, z = list(map(int, input().split()))
    edges.append((x, y, z))	# 节点1、节点2、权值

# 将所有边按权值排序
edges.sort(key = lambda item: item[2])

# 构造最小生成树(mst)
for e in edges:
    if len(mst) == n-1:
    	break
    x, y, z = e
    rx = find_root(x, root)
    ry = find_root(y, root)
    if rx == ry:	# 如果两个节点连通
        continue
    mst.append(e)
    root[rx] = root[ry]	# 连通两个节点

你可以在洛谷 P3366练习kruskal算法。