最小生成树kruskal算法(贪心算法)

【问题描述】Kruskal算法解决的是带权重的无向图上连接所有顶点的耗费最小的生成树。

【输入形式】在屏幕上输入顶点个数和连接顶点间的边的权矩阵。

【输出形式】顺序输出按照贪心选择加入到MST中的每条边的顶点编号(编号小的在前)及权值。

【样例1输入】

8

0 15 7 0 0 0 0 10

15 0 0 0 0 0 0 0

7 0 0 9 12 5 0 0 

0 0 9 0 0 0 0 0

0 0 12 0 0 6 0 0

0 0 5 0 6 0 14 8

0 0 0 0 0 14 0 3

10 0 0 0 0 8 3 0

【样例1输出】

7 8 3

3 6 5

5 6 6

1 3 7

6 8 8

3 4 9

1 2 15

【样例说明】

 输入:顶点个数为8。连接顶点间边的权矩阵大小为8行8列,位置[i,j]上元素值表示第i个顶点到第j个顶点的距离,0表示两个顶点间没有边连接。

 输出:顺序输出按照贪心选择加入到MST中的每条边的顶点编号(编号小的在前)及权值。

【评分标准】根据输入得到准确的输出。

import numpy as np
import heapq


class edge(object):
    def __init__(self, come=0, to=0, dis=0):
        self.come = come
        self.to = to
        self.dis = dis

    def __repr__(self):
        pass

    def __lt__(self, other):
        return self.dis < other.dis


class Heap(object):
    def __init__(self):
        self._queue = []

    def push(self, item):
        heapq.heappush(self._queue, item)

    def pop(self):
        if self._queue:
            return heapq.heappop(self._queue)
        else:
            return None

    def heapify(self):
        heapq.heapify(self._queue)

    @property
    def queue(self):
        return self._queue


"""class Unionfind(object):
    def __init__(self, nodes):
        self.fatherDict = {}  # key:node, value:father
        self.sizeDict = {}  # key:node,value:节点所在集合有多少个节点
        for node in nodes:
            self.fatherDict[node] = node
            self.sizeDict[node] = 1

    def find(self, node):
        stack = []
        father = self.fatherDict[node]
        while father != node:
            stack.append(node)
            node = father
            father = self.fatherDict[node]
        while stack:
            self.fatherDict[stack.pop()] = father
        return father

    def issame(self, a, b):
        return self.find(a) == self.find(b)

    def union(self, a, b):
        if a is None or b is None:
            return
        aHead = self.find(a)
        bHead = self.find(b)
        if aHead != bHead:
            asize = self.sizeDict[aHead]
            bsize = self.sizeDict[bHead]
            if asize <= bsize:
                self.fatherDict[aHead] = bHead
                self.sizeDict[bHead] = asize + bsize
            else:
                self.fatherDict[bHead] = aHead
                self.sizeDict[aHead] = asize + bsize"""


def find(x):
    if x == pre[x]:
        return x
    else:
        pre[x] = find(pre[x])
        return pre[x]


# def find(x):
#     r = x
#     while r != pre[r]:
#         r = pre[r]
#     i = x
#     while i != r:
#         j = pre[i]
#         pre[i] = r
#         i = j
#     return r


def join(x, y):
    pre[find(x)] = find(y)


# def join(x, y):
#     rank = [0]*100
#     root1 = find(x)
#     root2 = find(y)
#     if root1 == root2:
#         return
#     if rank[root1] < rank[root2]:
#         pre[root1] = root2
#     else:
#         if rank[root1] == rank[root2]:
#             rank[root1] += 1
#         pre[root2] = root1


def kruskal(c):
    Q = Heap()
    for i in c:
        Q.push(i)
    while Q.queue:
        u = Q.pop()
        if find(u.come) != find(u.to):
            print(u.come+1, u.to+1, u.dis)
            join(u.come, u.to)
        Q.heapify()


def main():
    n = int(input())
    a = []
    c = []
    global pre
    pre = []
    for i in range(n):
        a.append(list(map(int, input().rstrip().split())))
    b = np.array(a).reshape(n, n)
    for i in range(n):
        for j in range(i, n):
            if b[i, j]:
                node = edge(i, j, b[i, j])
                c.append(node)
    for i in range(0, n):
        pre.append(i)
    kruskal(c)


if __name__ == '__main__':
    main()

"""
8
0 15 7 0 0 0 0 10
15 0 0 0 0 0 0 0
7 0 0 9 12 5 0 0
0 0 9 0 0 0 0 0
0 0 12 0 0 6 0 0
0 0 5 0 6 0 14 8
0 0 0 0 0 14 0 3
10 0 0 0 0 8 3 0
"""

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值