题目链接: 冗余连接
树可以看成是一个图(拥有 n 个节点和 n - 1 条边的连通无环无向图)。
现给定一个拥有 n 个节点(节点标号是从 1 到 n)和 n 条边的连通无向图,请找出一条可以删除的边,删除后图可以变成一棵树。
输出一条可以删除的边。如果有多个答案,请删除标准输入中最后出现的那条边。如果边的两个节点已经出现在同一个集合里,说明着边的两个节点已经连在一起了,再加入这条边一定就出现环了。
那么从前向后将边加入并查集,如果要加入的边的节点已经在并查集中,那么就将其删掉。
#include <bits/stdc++.h>
using namespace std;
int n;
vector<int> father(1001, 0);
void init(){
for(int i = 0; i <= n; i++){
father[i] = i;
}
}
int find(int t){
return t == father[t] ? t : father[t] = find(father[t]);
}
bool isSame(int u, int v){
u = find(u);
v = find(v);
return u == v;
}
void join(int u, int v){
u = find(u);
v = find(v);
if(u == v){
return;
}
father[v] = u;
}
int main(){
int s,t;
cin >> n;
init();
for(int i = 0; i < n; i++){
cin >> s >> t;
if(!isSame(s, t)){
join(s,t);
}else{
cout << s << ' ' << t << endl;
return 0;
}
}
}
同样的,那么力扣这道题目我们也能够轻松拿下:
class Solution {
private:
vector<int> father;
public:
void init(int n){
for(int i = 0; i <= n; i++){
father[i] = i;
}
}
int find(int t){
return father[t] == t ? t : father[t] = find(father[t]);
}
bool isSame(int u, int v){
u = find(u);
v = find(v);
return u == v;
}
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) {
father = vector<int>(1001, 0);
init(edges.size());
for(auto& edge : edges){
if(isSame(edge[0], edge[1])){
return edge;
}else{
join(edge[0], edge[1]);
}
}
return {};
}
};