力扣https://leetcode.cn/problems/redundant-connection/
树可以看成是一个连通且 无环 的 无向 图。
给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。
请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的边。
示例 1:
输入: edges = [[1,2], [1,3], [2,3]]
输出: [2,3]
思路:并查集,一般用来区分多个集合的题目都可以用并查集处理,本题其实就是去找一个图是否构成了环,除了拓扑排序,应该想到并查集中看合并的时候,两个元素的father是否相同,如果相同那么说明已经在一个集合里了,此时再加一个边肯定会构成一个环。
像本题,其实不太适合用拓扑排序,应该需要在过程中动态的查看构成环的愿意。
//在大小固定的情况下,用数组比用hash的执行用时和内存上要更快一些
//对于并查集而言并不一定都需要记录每个集合中元素的个数,视题目的需求而定
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
int n=edges.size();
father=vector<int>(n+1);
for(int i=0;i<=n;++i)
father[i]=i;
for(auto&k:edges){
if(!merge(k[0],k[1]))return k;
}
return edges[edges.size()-1];
}
vector<int> father;
bool merge(int a,int b){
int roota=find_root(a);
int rootb=find_root(b);
if(roota==rootb)return false;
father[rootb]=roota;
return true;
}
int find_root(int a){
while(a!=father[a]){
a=father[a];
}
return a;
}
};