题目
https://leetcode-cn.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/
并查集
对于Alice来说当图中只有Alice的独占边和公共边时要求整个图是连通的,也就是说整个图的连通分量只有一个。
同理,对于Bob来说当图中只有Bob的独占边和公共边时也要求整个图是连通的。
题目要求删除最多的边,也就是要保留最少的边,可以通过给含有n个节点的无向图添加边来满足上面的要求。
添加边的策略是优先添加公共边,公共边处理完成后再分别处理Alice和Bob的独有边。
添加公共边或者独有边时,如果当前边的两个节点已经处在同一个连通分量中时,说明这条边是多余的,ans++。
class Solution {
public int maxNumEdgesToRemove(int n, int[][] edges) {
UnionFind ufa = new UnionFind(n);
UnionFind ufb = new UnionFind(n);
// 节点编号改为从0开始
for (int[] edge : edges) {
--edge[1];
--edge[2];
}
int ans = 0;
for (int[] edge : edges) {
if (edge[0] == 3) {
if (!ufa.union(edge[1], edge[2])) {
ans++;
} else {
ufb.union(edge[1], edge[2]);
}
}
}
for (int[] edge : edges) {
if (edge[0] == 1) {
if (!ufa.union(edge[1], edge[2])) {
ans++;
}
} else if (edge[0] == 2) {
if (!ufb.union(edge[1], edge[2])) {
ans++;
}
}
}
if (ufa.getCount() != 1 || ufb.getCount() != 1) {
return -1;
}
return ans;
}
class UnionFind {
private int[] parent;
private int count;
public UnionFind(int n) {
parent = new int[n];
count = n;
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
public int find(int x) {
while (x != parent[x]) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
public boolean union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY)
return false;
parent[rootX] = parent[rootY];
count--;
return true;
}
public int getCount() {
return count;
}
}
}