图 - 最小生成树

#!/usr/bin/env python3.3
# -*- coding:utf-8 -*-
# Copyright 2013

'''
无向图最小生成树:
1)kruskal算法:将所有的边按权值从小到大排序,顺序遍历把两个顶点不在同一个连通分量的边添加到最小生成树
2)Prim算法:从单一顶点开始,逐条添加连接最小生成树与一个不在树中的顶点的最小权边
'''

def mst_kruskal(graph, graph_size):
    # 并查集
    ufs = UnionFindSet()
    for v in range(graph_size):
        ufs.make_set(v)
    # 将所有的边按权值从小到大排序
    edge_queue = []
    for u in range(graph_size):
        for v in range(graph_size):
            if graph[u][v] is not None:
                edge_queue.append((graph[u][v], u, v))
    edge_queue.sort()

    mst = []
    mst_weight = 0
    for edge in edge_queue:
        # 判断两个顶点是否在同一个连通分量中
        weight, u, v = edge
        if ufs.find(u) != ufs.find(v):
            # 把边加入到最小生成树
            ufs.union(u, v)
            mst.append((u, v))
            mst_weight += weight
    return mst, mst_weight

def mst_prim(graph, graph_size):
    visit_set = {0}
    low_weight_from = [0] * graph_size
    low_weight = [w for w in graph[0]]
    low_weight[0] = 0

    mst = []
    mst_weight = 0
    for repeat in range(1, graph_size):
        # 查找最小权值顶点
        k = None
        for v in range(graph_size):
            if v not in visit_set and low_weight[v] is not None:
                if k is None or low_weight[v] < low_weight[k]:
                    k = v
        # 更新相邻顶点权值
        for v in range(graph_size):
            if v not in visit_set and graph[k][v] is not None:
                if low_weight[v] is None or graph[k][v] < low_weight[v]:
                    low_weight_from[v] = k
                    low_weight[v] = graph[k][v]
        # 把边加入到最小生成树
        mst.append((low_weight_from[k], k))
        mst_weight += low_weight[k]
        visit_set.add(k)
    return mst, mst_weight

 

posted @ 2013-04-30 00:57  Leung文  阅读(186)  评论(0编辑  收藏  举报