# 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
}
```