我正在尝试实现Kruskal的算法,在Python中找到最小生成树来解决在线判断的问题,但我遇到了时间限制问题。该问题按递增顺序给出一系列边缘,并询问是否可以使用最小生成树。可以看到完整的问题规范here.
以下是我的问题代码:
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"
代码首先为所有可能的顶点创建不相交的集合。然后,对于每个边缘,它检查两个顶点中的每一个所在的集合是否不同。如果是,则将两组与联合操作组合。组合集中的每个顶点都是新创建的组合集的成员。如果顶点已经连接,则跳过它们。我认为我的代码的问题是必须在行中更新集合的次数:
for vertice in newSet:
dict1[num] = newSet
是否有更快的方法来更新集合以检查它们是否相等?此操作大约需要O(顶点^ 2)时间,并且当最多有100,000个顶点时需要太长时间。
答案 0 :(得分:3)
关键是为集合使用适当的数据结构。合并节点集和测试以查看是否有任何两个节点在同一个集合中是一个典型的计算机科学问题,称为“union-find”。
这方面的最佳数据结构很简单,如下所述:
http://www.algorithmist.com/index.php/Union_Find
使用这种结构,你可以在非常恒定的时间内合并集合并测试相等性,这使得你对Kruskal算法(你提供了预先排序的边缘列表)的实现非常线性。