685.冗余链接2

leetcode

建立出边邻接表,节点入度数组。

因为需要返回最后的一个可以去除的边,故倒序删除边,删除后满足树的条件则表明该边为要找的冗余边。

为树的条件:

  1. 有且只有一个入度大于0的点(防止成环)
  2. 且最长路径的步数和节点数相等(防止有独立的多块不联通的图)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    func findRedundantDirectedConnection(edges [][]int) []int {
    to := make(map[int][]int)
    degrees := make([]int, len(edges)+1)

    for _, edge := range edges {
    to[edge[0]] = append(to[edge[0]], edge[1])
    degrees[edge[1]]++
    }

    // fmt.Printf("to: %v\n", to)
    // fmt.Printf("degress: %v\n", degrees)

    valid := func() bool {
    var root int
    for i := 1; i < len(degrees); i++ {
    if degrees[i] == 0 {
    root = i
    }

    // 有入度大于0的点,表示有环
    if degrees[i] > 1 {
    return false
    }
    }

    // 没有入度为0的点,表示有环
    if root == 0 {
    return false
    }

    seen := []int{}

    var bfs func(int)

    bfs = func(root int) {
    seen = append(seen, root)
    for _, c := range to[root] {
    bfs(c)
    }
    }

    bfs(root)

    return len(seen) == len(edges)
    }

    // 倒序删除边
    for i := len(edges) - 1; i >= 0; i-- {
    edge := edges[i]
    for j, t := range to[edge[0]] {
    if t == edge[1] {
    to[edge[0]] = append(to[edge[0]][:j], to[edge[0]][j+1:]...)
    break
    }
    }
    degrees[edge[1]]--
    if valid() {
    return edges[i]
    }

    // 还原
    to[edge[0]] = append(to[edge[0]], edge[1])
    degrees[edge[1]]++
    }

    return []int{}
    }

685.冗余链接2
https://blog.jerrylee.me/2021/09/d38dabc86412.html
作者
Jerry Lee
发布于
2021年9月20日
许可协议