Disjoint 设置路径压缩运行时间错误
Posted
技术标签:
【中文标题】Disjoint 设置路径压缩运行时间错误【英文标题】:Disjoint Sets path compression running time error 【发布时间】:2016-08-31 06:43:07 【问题描述】:我现在正在学习在线数据结构课程。这是我的合并和查找算法的 Python 实现。我按照说明进行操作,但运行时间远远超出了限制。任何人都可以看看吗?它应该是一个简单的。谢谢。
我们必须进行“m”合并或联合操作。 ????????????????????????????????????????????????(??????)和 ????????????????????????(??????) 是两个具有真实数据的表的数量。如果 ????????????????????????????????????????????(???? ) ̸=????????????????????????(????),复制表中的所有行?????????? ???????????????(??????) 到表?????????????????????????????? ???????????????(??????),然后清表????????????????????????? ?(????) 而不是真实数据,而是将符号链接放入????????????????????????????????? ???????????(????) 进去。答案是列表行的最大表格大小。操作顺序示例:
5 5
1 1 1 1 1
3 5
2 4
1 4
5 4
5 3
输入显示有 5 个表,我们要做 5 次操作。每个表的大小为 1。以下五行显示我们要将 source5 合并到destination3,将source4 合并到destination2... 输出应该是:
2
2
3
5
5
说明:在此示例中,所有表最初都只有 1 行数据。考虑合并操作:
表 5 中的所有数据都复制到表号 3。表 5 现在只包含指向表 3 的符号链接,而表 3 有 2 行。 2 成为新的最大尺寸。
2 和 4 的合并方式与 3 和 5 相同。
我们试图合并1和4,但是4有一个符号链接指向2,所以我们实际上把2号表的所有数据复制到1号表中,清空2号表放指向其中表号 1 的符号链接。表 1 现在有 3 行数据,3 成为新的最大大小。
从 4 开始遍历符号链接的路径,我们有 4 → 2 → 1,从 5 开始的路径是 5 → 3。所以我们实际上是在合并表 3 和表 1。我们从表中复制所有行1号表插入3号表,现在3号表有5行数据,是新的最大值。
现在所有表都直接或间接指向表 3,因此所有其他合并不会改变任何内容。
说明: 思考如何使用带路径压缩的不相交集联合和秩启发式联合来解决这个问题。特别是,您应该将执行联合/查找操作的数据结构与表的合并区分开来。如果要求将第一个表合并到第二个,但是第二个表的rank小于第一个表的rank,在Disjoint Set Union数据结构中合并时可以忽略请求的顺序,加入对应的节点到第二个表到与第一个表对应的节点,而不是在你的不相交集联合中。但是,您需要将请求合并第一个表的实际第二个表的编号存储在相应的不相交集的父节点中,并且您需要在不相交集联合的节点中添加一个额外的字段来存储它。
这是我使用秩启发式和路径压缩实现它的代码:
# python2
import sys
n, m = map(int, sys.stdin.readline().split())
lines = list(map(int, sys.stdin.readline().split()))
rank = [1] * n
rank_original=[1]*n
parent = list(range(0, n))
ans = max(lines)
rank=lines
for i in range(len(lines)):
rank[i]=lines[i]
rank_original[i]=lines[i]
def getParent(i):
# find parent and compress path
if i!=parent[i]:
parent[i]=getParent(parent[i])
return parent[i]
def merge(destination, source):
realDestination, realSource = getParent(destination), getParent(source)
if realDestination == realSource:
return False
if rank[realDestination]>=rank[realSource]:
parent[realSource]=realDestination
rank[realDestination] += rank[realSource]
rank_original[realDestination]=rank[realDestination]
else:
parent[realDestination]=realSource
rank[realSource]+=rank[realDestination]
rank_original[realDestination]=rank[realSource]
rank_original[source]=0
return True
for i in range(m):
destination, source = map(int, sys.stdin.readline().split())
merge(destination - 1, source - 1)
ans=max(rank)
print(ans)
【问题讨论】:
【参考方案1】:问题是您在每一轮的整个数据上调用max
,因此具有O(nm)
时间复杂度。不要在初始数据上调用max
,而是存储结果并在每次合并后更新它,以防目标表大于当前最大值。使用路径压缩,这将导致 O(m + n)
时间复杂度。
n, m = map(int, raw_input().split())
rank = [0] + map(int, raw_input().split())
parent = range(n + 1)
current_max = max(rank)
def find_parent(x):
if parent[x] != x:
parent[x] = find_parent(parent[x])
return parent[x]
for source, dest in (map(int, raw_input().split()) for _ in xrange(m)):
source, dest = find_parent(source), find_parent(dest)
if source != dest:
if rank[source] > rank[dest]:
source, dest = dest, source
parent[source] = dest
rank[dest] += rank[source]
current_max = max(current_max, rank[dest])
print current_max
【讨论】:
我使用了你的技巧,但系统仍然显示:失败案例#11/132:超出时间限制(使用时间:11.99/6.00,使用内存:158879744/536870912。) @patrickkkkk 根据提供的信息,很难找出可能是什么问题。如果您可以将说明、示例输入和预期输出添加到问题中,您可能会得到更好的结果。不需要全尺寸输入,只是一个有效的示例。 感谢您的回复。我已经编辑了我的问题。我想我正确地使用了排名启发式和路径压缩,但为什么要花那么多时间来运行呢? @patrickkkkk:根据附加信息更新了我的答案。 真的好用!我终于明白了我原来的代码出了什么问题。非常感谢尼米!以上是关于Disjoint 设置路径压缩运行时间错误的主要内容,如果未能解决你的问题,请参考以下文章