[路飞] 684. 冗余连接

194 阅读2分钟

题目描述

树可以看成是一个连通且 无环 的 无向 图。

给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。

请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的边。

解题思路

数据结构,算法

并查集,记录已经联通的点

思路

首先,题目要求我们删除一条边,那么对于一个环形,有可能会有多个解的情况,所以这时候我们要做的是删除最后一条边

找到一条可以删除的边

我们如果要确定一条边可以被删除,那么一定是这条边的两个节点已经被连接到了另一个 root 上,因此如果在并查集中,我们可以确定两个节点已经被链接,那么一定这条边可以作为我们的候选答案

过程

我们遍历 edges,对于每条边的两个点,我们看他们是否已经都被连接到了同一个 root 上,如果是的话,那么这是一个可选的答案,最终返回最后一个答案

代码

/**
 * @param {number[][]} edges
 * @return {number[]}
 */
var findRedundantConnection = function (edges) {
  const n = edges.length
  const u = new UnionSet(n)
  let ret

  for (const item of edges) {
    const node1 = item[0]
    const node2 = item[1]

    if (u.get(node1) === u.get(node2)) {
      ret = item
    }
    u.merge(node1, node2)
  }

  return ret
}

class UnionSet {
  constructor(n) {
    this.fa = []
    for (let i = 0; i <= n; i++) {
      this.fa[i] = i
    }
  }

  get(x) {
    return (this.fa[x] = this.fa[x] === x ? x : this.get(this.fa[x]))
  }

  merge(a, b) {
    this.fa[this.get(b)] = this.get(a)
  }
}