In this problem, a tree is an undirected graph that is connected and has no cycles.
You are given a graph that started as a tree with n
nodes labeled from 1
to n
, with one additional edge added. The added edge has two different vertices chosen from 1
to n
, and was not an edge that already existed. The graph is represented as an array edges
of length n
where edges[i] = [ai, bi]
indicates that there is an edge between nodes ai
and bi
in the graph.
Return an edge that can be removed so that the resulting graph is a tree of n
nodes. If there are multiple answers, return the answer that occurs last in the input.
Example 1:
Input: edges = [[1,2],[1,3],[2,3]] Output: [2,3]
Example 2:
Input: edges = [[1,2],[2,3],[3,4],[1,4],[1,5]] Output: [1,4]
Constraints:
n == edges.length
3 <= n <= 1000
edges[i].length == 2
1 <= ai < bi <= edges.length
ai != bi
- There are no repeated edges.
- The given graph is connected.
【C++】
1. 并查集
class UF {
vector<int> id, size;
public:
UF(int n): id(n), size(n, 1) {
iota(id.begin(), id.end(), 0); // iota函数可以把数组初始化为0到n-1
}
int find(int p) {
while (p != id[p]) {
id[p] = id[id[p]]; // 路径压缩,使得下次查找更快
p = id[p];
}
return p;
}
void connect(int p, int q) {
int i = find(p), j = find(q);
if (i != j) {
// 按秩合并:每次合并都把深度较小的集合合并在深度较大的集合下面
if (size[i] < size[j]) {
id[i] = j;
size[j] += size[i];
} else {
id[j] = i;
size[i] += size[j];
}
}
}
bool isConnected(int p, int q) {
return find(p) == find(q);
}
};
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
int n = edges.size();
UF uf(n + 1);
for (auto e: edges) {
int u = e[0], v = e[1];
if (uf.isConnected(u, v)) {return e;}
uf.connect(u, v);
}
return vector<int>{-1, -1};
}
};
2. 粗暴循环打法
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
int n = 0;
for(const auto &e : edges) {
n = max(e[0]+1, n);
n = max(e[1]+1, n);
}
parent_ = vector<int>(n);
for(int i = 0; i < n; ++i) parent_[i] = i;
for(auto it = edges.begin(); it != edges.end(); ++it) {
const auto &e = *it;
if(GetParent(e[0]) == GetParent(e[1])) {
if(e[0] < e[1]) return {e[0], e[1]};
else return {e[1], e[0]};
}
parent_[GetParent(e[0])] = GetParent(e[1]);
}
return {};
}
private:
int GetParent(int x) {
if(parent_[x] != x) parent_[x] = GetParent(parent_[x]);
return parent_[x];
}
vector<int> parent_;
};
【Java】
class Solution {
private int[] parent_;
public int[] findRedundantConnection(int[][] edges) {
int n = 0;
for(int[] e : edges) {
n = Math.max(e[0]+1, n);
n = Math.max(e[1]+1, n);
}
parent_ = new int[n];
for(int i = 0; i < n; ++i) parent_[i] = i;
for(int[] e : edges) {
if (GetParent(e[0]) == GetParent(e[1])) {
if(e[0] < e[1]) return new int[]{e[0], e[1]};
else return new int[]{e[1], e[0]};
}
parent_[GetParent(e[0])] = GetParent(e[1]);
}
return new int[]{};
}
private int GetParent(int x) {
if(parent_[x] != x) parent_[x] = GetParent(parent_[x]);
return parent_[x];
}
}