SDE / Frontend · Coding

Amazon Coding:让图全连通,最少移动几条边?

用边预算与连通分量证明c−1,并说明重接操作、重复边和不可行条件。

题目重点:用边预算与连通分量证明c−1,并说明重接操作、重复边和不可行条件。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 题目明确并查集求all connected需要移动几条边;没有正式移动限制,本文采用无向网络标准重接合同:一次移除已有边并把它接到任意两个节点。
  • n≥1,节点0..n−1,每条边是一份可移动资源,重复边/自环也可重接;不新增资源。实际原题如限制端点、不能断开原分量或只移动单端须重新核。
  • 不可行返回−1,是训练输出政策;原题未给正式规模和返回合同。

解题路线

  1. 先求连通分量c。每条跨分量新增连接最多让c减1,所以至少需要c−1次移动。这是下界,但还要证明有这么多不破坏原连接的边可借。
  2. 每个分量保留一棵生成树,全部生成森林用n−c条边,其余m−(n−c)是可挪用冗余资源。若≥c−1即可把分量连成链或星形;条件等价m≥n−1。移动生成森林外的边不会拆开原分量,达到下界。
  3. DSU一边扫描一边union,有效union减少c;同root的边是冗余,包括自环与平行重复。union by size加path compression避免长链。只求次数不需保存具体冗余边,如果要构造操作方案才保留edge ID和每个分量代表。
  4. m<n−1时,任何无向连通图至少需n−1条非自环有效连接,重接不能增加资源数,故无解。n=1按零次已连通,不能因为没有边错误判−1。
  5. 如果题目不允许拿自环/平行边、某些边锁定不可移动、移动费用不同或只接指定邻点,简单m判据不再充分。论文/标准题名不能替题目缺失的操作规则,文章仅声明标准训练合同。
  6. 独立参考枚举n≤4全部简单图,用真实“移一条边到另一个位置”的状态图反向BFS找最少操作,而非用同一分量公式作为期望;75图与2自环/平行资源样例通过。

手动走一遍

n=4,边(0,1),(1,2),(2,0),分量{0,1,2}/{3},三角环中一边可移到(2,3),1次。只有(0,1),(1,2)时边数2<3,没有足够连接资源,−1。n=4有3份(0,1)平行边时,保留一份,将另两份连到2、3,2次。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def minimum_relocations(n, edges):
    """Keep edge count; one operation removes an edge and reconnects it anywhere."""
    if type(n) is not int or n < 1:
        raise ValueError('positive vertex count required')
    parent = list(range(n))
    sizes = [1] * n
    count = n
    def find(x):
        while parent[x] != x:
            parent[x] = parent[parent[x]]
            x = parent[x]
        return x
    edge_count = 0
    for u,v in edges:
        if type(u) is not int or type(v) is not int or not (0 <= u < n and 0 <= v < n):
            raise ValueError('vertex outside range')
        edge_count += 1
        a,b = find(u),find(v)
        if a != b:
            if sizes[a] < sizes[b]:
                a,b = b,a
            parent[b] = a
            sizes[a] += sizes[b]
            count -= 1
    return count-1 if edge_count >= n-1 else -1

复杂度

O((n+m)α(n))时间、O(n)DSU工作空间;输入可流式扫描不必保存m边。构造重接清单额外O(m+n)边/代表存储;α是逆Ackermann函数,不直接把所有union find一律宣称常数。

易错点与追问

容易失分的边界

  • 只数分量没查边资源。
  • 每个同root边丢弃后无法构造操作。
  • 自环不算原资源却套m判据。
  • 有向图套无向生成森林。
  • n=1判无解。

继续深挖

  • 要输出每次移哪条边怎样保存edgeID?
  • 边不可移动时判据如何变?
  • 有向强连通为何不是c−1?
  • 加权移动最小成本怎么扩展?
✓已复制微信号!