题目类型:N个点M条边的无向图,删除边使无向图连通无环(生成树)。
【思路】并查集
合并函数返回是否连通的bool类型,以此判断该边是否多余。
遍历每条边,合并边的两端点。
例题一
class Solution {
public:
int fa[1005];
void init(int n) {
for (int i = 1; i <= n; i++)
fa[i] = i;
}
int get(int x) {
if(fa[x] == x)
return x;
return fa[x] = get(fa[x]);//路径压缩,防止链式结构
}
bool merge(int x, int y) {
if(get(x)==get(y))
return false;
fa[get(x)] = get(y);
return true;
}
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
init(1000);
for(auto edge:edges){
if(!merge(edge[0],edge[1]))
return {edge[0],edge[1]};
}
return {};
}
};
例题二
【思路】维护两个并查集
class Solution {
public:
using PII=pair<int,int>;
int f1[100010];
int f2[100010];
void init(int n) {
for (int i = 1; i <= n; i++){
f1[i] = i;
f2[i] = i;
}
}
int get(int x,int *fa) {
if(fa[x] == x)
return x;
return fa[x] = get(fa[x],fa);//路径压缩,防止链式结构
}
bool merge(int x, int y,int *f) {
if(get(x,f)==get(y,f))
return false;
f[get(x,f)] = get(y,f);
return true;
}
int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {
int m=edges.size();
vector<PII> t3,t1,t2;
int res=0;
for(int i=0;i<m;i++){
if(edges[i][0]==3)
t3.push_back({edges[i][1],edges[i][2]});
else if(edges[i][0]==1)
t1.push_back({edges[i][1],edges[i][2]});
else
t2.push_back({edges[i][1],edges[i][2]});
}
init(n);
for(int i=0;i<t3.size();i++){
if(!merge(t3[i].first,t3[i].second,f1))
res++;
else
merge(t3[i].first,t3[i].second,f2);
}
for(int i=0;i<t1.size();i++){
if(!merge(t1[i].first,t1[i].second,f1))
res++;
}
for(int i=0;i<t2.size();i++){
if(!merge(t2[i].first,t2[i].second,f2))
res++;
}
int cnt1=0,cnt2=0;
for(int i=1;i<=n;i++){
if(f1[i]==i)
cnt1++;
if(f2[i]==i)
cnt2++;
}
if(cnt1!=1 || cnt2!=1) return -1;
return res;
}
};