---
# System prepended metadata

title: 684. Redundant Connection
tags: [C++, LeetCode]

---

# LeetCode 684. Redundant Connection

https://leetcode.com/problems/redundant-connection/description/

## 題目大意

給定無向圖，拔掉一邊使得圖變成樹 (原圖 `n` 個節點、`n` 條邊且無 loop，樹的話應該只會有 `n-1` 條邊)  
回傳要拔掉哪條邊，如果答案很多種，依題目輸入邊的順序回傳最後面的那條邊

## 思考

樹不能有 cycle ，所以找出圖中的 cycle 依照輸入順序拔掉最後輸入的那條邊即可

你可以使用 DFS or BFS 來找 cycle ，或者這題我們可以用 disjoint set 來幫忙：  
想法就是 cycle 會繞一圈嘛，那麼當我們執行 union 時就會遇到兩點已經屬於同個 set 的情況

我們視 disjoint set 的 union 跟 find 都是 $O(1)$ 的話  
使用 DFS (or BFS) 時間複雜度為 $O(n^2)$ ($\forall (u, v)\in E$, using DFS (or BFS) to check whether $u$ and $v$ are connected takes $O(n)$)；使用 disjoint set 的方法時間複雜度只有 $O(n)$

### C++ 參考解答

```cpp!
class DisjointSet
{
public:
    DisjointSet(size_t n) : parent(n), rank(n)
    {
        iota(parent.begin(), parent.end(), 0);
    }

    bool unionSet(int x, int y)
    {
        int rootX = find(x);
        int rootY = find(y);

        if (rootX == rootY)
            return false;

        if (rank[rootX] > rank[rootY])
            swap(rootX, rootY);
        parent[rootX] = rootY;
        if (rank[rootX] == rank[rootY])
            ++rank[rootX];
        return true;
    }

    int find(int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); }

private:
    vector<int> parent;
    vector<int> rank;
};

class Solution
{
public:
    vector<int> findRedundantConnection(vector<vector<int>> &edges)
    {
        DisjointSet uf(edges.size() + 1);

        for (const auto &edge : edges)
        {
            const int u = edge[0];
            const int v = edge[1];
            if (!uf.unionSet(u, v))
                return edge;
        }

        throw;
    }
};
```

### Go 參考解答

```go!
func findRedundantConnection(edges [][]int) []int {
	n := len(edges)
	parent := make([]int, n+1)
	rank := make([]int, n+1)

	for i := 1; i <= n; i++ {
		parent[i] = i
		rank[i] = 1
	}

	var find func(int) int
	find = func(x int) int {
		if parent[x] != x {
			parent[x] = find(parent[x])
		}
		return parent[x]
	}

	union := func(x, y int) bool {
		rootX, rootY := find(x), find(y)
		if rootX == rootY {
			return false
		}
		if rank[rootX] > rank[rootY] {
			parent[rootY] = rootX
		} else if rank[rootX] < rank[rootY] {
			parent[rootX] = rootY
		} else {
			parent[rootX] = rootY
			rank[rootX]++
		}
		return true
	}

	for _, edge := range edges {
		if !union(edge[0], edge[1]) {
			return edge
		}
	}

	return nil
}
```