简体   繁体   English

改进查找最小生成树的实现

[英]Improving Implementation of Finding a Minimum Spanning Tree

I am trying to implement Kruskal's algorithm to find a minimum spanning tree in Python to solve a question on an online judge, but I am running into time limit problems. 我正在尝试实现Kruskal的算法,以在Python中找到最小生成树来解决在线判断的问题,但我遇到了时间限制问题。 The question gives a series of edges in increasing order and asks if a minimum spanning tree is possible. 该问题按递增顺序给出一系列边缘,并询问是否可以使用最小生成树。 Full problem specifications can be seen here. 这里可以看到完整的问题规范

Here is my code for the problem: 这是我的问题代码:

import sys
raw_input = sys.stdin.readline
line = map(int, raw_input().split())
n = line[0]
m = line[1]
dict1 = {}
lists = []

for i in xrange(1, n + 1):
    dict1[i] = set([i])

for i in xrange(m):
    edge = map(int, raw_input().split())
    a = edge[0]
    b = edge[1]
    if dict1[a] != dict1[b]:
        newSet = dict1[a].union(dict1[b])
        for vertice in newSet:
            dict1[num] = newSet
        lists.append(i + 1)

check = all(dict1[x] == dict1[1] for x in dict1.keys())

if check:
    for i in lists:
        print i
else:
    print "Disconnected Graph"

The code first creates disjoint sets for all possible vertices. 代码首先为所有可能的顶点创建不相交的集合。 Then for each edge, it checks if the sets where each of the two vertices lie are different. 然后,对于每个边缘,它检查两个顶点中的每一个所在的集合是否不同。 If they are, then the two sets are combined with a union operation. 如果是,则将两组与联合操作组合。 Each vertex in the combined set is a member of the newly created combined set. 组合集中的每个顶点都是新创建的组合集的成员。 If the vertices are already connected, then they are skipped. 如果顶点已经连接,则跳过它们。 I think the problem with my code is the number of times the sets have to be updated in the lines: 我认为我的代码的问题是必须在行中更新集合的次数:

for vertice in newSet:
    dict1[num] = newSet

Is there a faster way to update the sets to check if they are equal? 是否有更快的方法来更新集合以检查它们是否相等? This operation is taking approximately O(vertices^2) time, and it takes too long when there are up to 100,000 vertices. 此操作大约需要O(顶点^ 2)时间,并且当有多达100,000个顶点时需要太长时间。

The key is to use the appropriate data structure for your sets. 关键是为您的集合使用适当的数据结构。 Merging sets of nodes and testing to see if any two nodes are in the same set is a classic computer science problem called "union-find". 合并节点集和测试以查看是否有任何两个节点在同一组中是一个典型的计算机科学问题,称为“union-find”。

The best data structure for this is easy and is described here: 这方面的最佳数据结构很简单,如下所述:

http://www.algorithmist.com/index.php/Union_Find http://www.algorithmist.com/index.php/Union_Find

Using this structure, you can merge sets and test for equality in pretty much constant time, which makes your implementation of Kruskal's algorithm (where you're provided with a pre-sorted list of edges) pretty much linear. 使用这种结构,你可以在非常恒定的时间内合并集合并测试相等性,这使得你对Kruskal算法(你提供了预先排序的边缘列表)的实现非常线性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM