【问题标题】:Find all pairs of nodes whose deletion disconnects graph查找删除断开图的所有节点对
【发布时间】:2018-11-13 17:08:55
【问题描述】:

给定无向的连通图,找到所有节点对(由一条边连接),其删除会使图断开连接。
没有平行边,也没有将节点连接到自身的边。

这个问题似乎类似于寻找一个连接的无向图的连接点(或桥)——但有一个转折点,我们必须删除由一条边连接的一对顶点(以及连接到该对的所有其他边) .

这是一道作业题。我一直在尝试解决它,阅读有关 DFS 和关节点算法(每个节点的 bookkeap 深度和低点)的信息 - 但这些方法都没有帮助解决这个特定问题。我已经检查了 Cormen 的 Intro to Algorithms,但没有任何主题适合自己(当然,这本书确实有 1500 页)。

虽然找到关节点确实也会(大多数时候)找到这样的一对,但有很多对不是关节点 - 考虑一个具有 4 个顶点、5 个边的图(正方形与单对角线):它有一对这样的对,但没有关节点(也没有桥)。

我迷路了。帮帮我,堆栈溢出,你是我唯一的希望。

【问题讨论】:

    标签: algorithm graph language-agnostic


    【解决方案1】:

    根据@MkjG 的建议更新我之前的答案,使用 DFS 计算关节点。

    设图为 G=(V,E) 且 V := {v_1, ..., v_n}_。对于 V 的每个子集 V',让 G_V' 是包含节点 V\V' 的节点诱导子图。对于连接的 G,如果 G_{v} 未连接,我们将 V in V 称为关节点。令 N_v 为 v 在 G 中的邻居集合。

    关节点可以通过 DFS 计算,请阅读here 了解有关该算法的更多信息。简而言之:

    1. 为 V 中的某个根节点 r 计算 DFS 树 T
    2. r 是一个关节点,如果它在 T 中有多个子节点
    3. V 中的任何其他节点 v 是一个关节点,当且仅当它在 T 中具有满足以下条件的子树 v':T 的子树 T' 中以 v' 为根的节点不具有到v

    设图 G 上的 DFS 的结果是 V 中节点 v 上的函数 c。c(v) 是 N_v 的子集,如果满足以下两个条件,它在 c(v) 中保持 v' :

    1. v' 是 T 中 v 的子代
    2. 以 v' 为根的 T 的子树 T' 中没有节点与 v 的祖先有后边

    注意,对于 T 的根节点 r,c(r) 是 r 的所有子节点的集合。函数 c 的计算时间为 O(n+m)。

    按如下方式计算分隔符对:

    # performs DFS on G for some root node r
    c = DFS(G,r)
    # computes articulation points of G and corresponding number of components
    aps = {}
    compCounts = {}
    for each v in V:
        numComps = |c(v)|
        if v != r:
            ++numComps
        if numComps > 1:
            add v to aps
            compCounts[v] = numComps
    # computes the set of all separator pairs containing at least on ap
    S = {}
    for each v in aps:
        numComps = compCounts[v]
        for each v' in N_v:
            if numComps > 2:
                # G_{v,v'} has at least two connected components
                add {v,v'} to S
            else:
                # if v' is an isolated node in G_{v}, then G_{v,v'} is connected
                if N_v' != {v}:
                    add {v,v'} to S
    # computes remaining separator pairs
    for each v in V \ aps:
        compute G_{v}
        # performs DFS on G_{v} for some root r_v != v
        c_v = DFS(G_{v},r_v)
        # adds separator pairs for articulation points of G_{v} in N_v
        for each v' in N_v:
            numComps = |c(v')|
            if v' != r_v:
                ++numComps
            if numComps > 1:
                add{v,v'} to S
    

    运行时间为 O(n * (n+m))

    【讨论】:

    • 我找到了在 O(V+E) 中执行此操作的算法:scholar.uwindsor.ca/cgi/… 您可以 CTRL+F 将其用于“分离对”。算法从第 3 章开始。不过感谢您的帮助:)
    • 这个算法要求我们在一个 2 连通树上进行操作,但我可以根据您的算法的第一部分(也是 n+m)从给定图创建 2 连通森林。
    • 这个链接实际上让算法更清晰:link.springer.com/content/pdf/10.1007/3-540-44541-2_8.pdf
    【解决方案2】:

    相当简单,也许不是最有效的:

    设图为 G=(V,E) 且 V := {v_1, ..., v_n}。对于 V 的每个子集 V',让 G_V' 是包含节点 V\V' 的节点诱导子图。进一步令 N>_v_i := {v_j in V : {v_i,v_j} in E and j > i} 是 G 中索引大于 i 的 v_i 的所有邻居的集合。最后,设 c(G) 为图的连通分量集。

    按如下方式计算对:

    pairs = {}
    for each v in V:
        compute G_{v}
        if G_{v} is unconnected:
            for each v' in N>_v:
                # Ensures that removal of v' does not render subgraph connected
                # (Note comment by MkjG)
                if |c(G_{v})| > 2 or {v'} not in c(G_{v}):
                    add {v,v'} to pairs
        else:
            for each v' in N>_v:
                compute G_{v,v'}
                if G_{v,v'} unconnected:
                    add {v,v'} to pairs
    

    可以在 O(m+n) 中通过 DFS 或 BFS 检查连接性。因此运行时间应该是 O(n * k * (m+n)),其中 k 是 G 的最大度数。

    【讨论】:

    • 不幸的是,我无法评论 TheWildHealer 给出的答案,但是,我认为这是错误的。作为反例,定义两个k-cliques G_1 和 G_2,k>1。添加两个额外的节点 s_1 和 s_2。将 s_1 和 s_2 与 G_1 和 G_2 中的所有节点连接起来。将 s_1 与 s_2 进一步连接。显然,删除 s_1 和 s_2 会使图形不连接。我没有证明,但我想删除任何 k 边不会。 2 边缘绝对是不够的。因此,一般来说,2-cuts 和可能的 k-cuts 不会让您解决这个问题。
    • @the_anonymous 第一种情况至少有一个小错误。考虑简单的 3 顶点 2 边图:(1-2-3)。由于 G_(2) 是未连接的,因此 (2,3) 被识别为一对,但事实并非如此:删除 (2,3) 会导致连接图 (1)。此外,第一种情况(删除一个节点导致未连接的图)基本上是铰接点(有一个额外的约束,它的邻居有一个邻居),即 O(m+n)。我不禁想知道是否有任何方法可以改进第二种情况,或者至少在单个 DFS 中首先从第一种情况中找到对。
    • 你说得对,我没有想到这种可能性。我编辑了我的答案以纠正这个错误。根据您的建议,我还使用更有效的算法添加了第二个答案,该算法使用 DFS 计算关节点。
    【解决方案3】:

    断开图的一组 k 条边称为 k-cut。您正在尝试枚举图形的所有 2-cut。

    This paper 描述了一种枚举图的所有切割的有效算法。应该可以对其进行调整以找到图形的所有 2-cut。

    【讨论】:

    • 不完全。据我了解,2-cut 只是通过删除一组边将图划分为两个子图。这里的条件更严格,因为边必须与一对相邻顶点相邻,并且也更宽松,因为任何 k-cut 都会这样做(唯一的条件是结果图不能连接)。我想我正在寻找基数为 2 的所有顶点分隔符。
    猜你喜欢
    • 2010-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多