题目:
- 树可以看成是一个连通且 无环 的 无向 图。
- 给定往一棵
n
个节点 (节点值1~n
) 的树中添加一条边后的图。添加的边的两个顶点包含在1
到n
中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为n
的二维数组edges
,edges[i] = [ a i a_i ai, b i b_i bi] 表示图中在 a i a_i ai 和 b i b_i bi 之间存在一条边。 - 请找出一条可以删去的边,删除后可使得剩余部分是一个有着
n
个节点的树。如果有多个答案,则返回数组edges
中最后出现的那个。
示例:
- 输入: e d g e s = [ [ 1 , 2 ] , [ 1 , 3 ] , [ 2 , 3 ] ] edges = [[1,2], [1,3], [2,3]] edges=[[1,2],[1,3],[2,3]]
- 输出: [ 2 , 3 ] [2,3] [2,3]
解题思路:并查集
采用并查集算法,从前往后遍历edges
里的每一条边,在将边加入到并查集前,先判断两节点是否处于相同的集合isSame(edges[i][0], edges[i][1])
,若已在同一集合,再将当前的边加入到集合将会导致出现环,此时直接将该边返回。
C++版整体代码:
class Solution {
public:
int n = 200005;
vector<int> father = vector<int>(n, 0);
// 并查集初始化
void init(){
for(int i = 0; i < n; i++) father[i] = i;
}
// 并查集寻根操作
int find(int u){
return u == father[u] ? u : father[u] = find(father[u]);
}
// 判断两个节点是否属于同一集合
bool isSame(int u, int v){
u = find(u);
v = find(v);
return u == v;
}
// 将v->u这条边加入并查集
void join(int u, int v){
u = find(u);
v = find(v);
if(u == v) return;
father[v] = u;
}
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
init();
for(int i = 0; i < edges.size(); i++){
if(isSame(edges[i][0], edges[i][1])) return edges[i];
else join(edges[i][0], edges[i][1]);
}
return {};
}
};