Disjoint设置路径压缩运行时错误

时间:2016-08-31 06:43:08

标签: python data-structures disjoint-sets

我现在正在参加在线数据结构课程。这是我的合并和查找算法的Python实现。我按照说明操作,但运行时间远远超出限制。有人可以看看吗?它应该是一个简单的。感谢。

我们必须做'合并'或联合行动。 ()和()是具有实际数据的两个表的数量。如果()̸=(),将table()中的所有行复制到table(),然后清除表()而不是真实数据,将符号链接放入()。答案是列表行的最大表大小。操作顺序的一个例子:

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行数据。考虑合并操作:

  1. 表5中的所有数据都被复制到表号3.表5现在只包含表3的符号链接,而表3有2行。 2成为新的最大尺寸。

  2. 2和4以与3和5相同的方式合并。

  3. 我们正在尝试合并1和4,但是4有一个指向2的符号链接,所以我们实际上将表号2中的所有数据复制到表号1,清除表号2并放入表1中的表号的符号链接。表1现在有3行数据,3表示新的最大大小。

  4. 从4遍历符号链接的路径我们有4→2→1,而5的路径是5→3。所以我们实际上是合并表3和1.我们从表中复制所有行数字1到表号3,现在表号3有5行数据,这是新的最大值。

  5. 现在所有表都直接或间接指向表3,因此所有其他合并都不会改变任何内容。

  6. 指令: 考虑如何使用不相交的集合联合与路径压缩和联合启发来解决这个问题。特别是,您应该在思考中分离从表的合并执行联合/查找操作的数据结构。如果要求您将第一个表合并到第二个表中,但第二个表的排名小于第一个表的排名,则可以在Disjoint Set Union数据结构中合并时加入请求的顺序并加入相应的节点到第二个表到第一个表对应的节点而不是你的Disjoint Set Union。但是,您需要存储请求合并相应Disjoint Set的父节点中的第一个表的实际第二个表的编号,并且您将需要在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 个答案:

答案 0 :(得分:0)

问题在于您在每一轮的整个数据上调用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