1489. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree
T: O(ElogE + n*Akeman + E*n*Akeman)
S: O(E + n)
```java
class Solution {
public List<List<Integer>> findCriticalAndPseudoCriticalEdges(int n, int[][] oEdges) {
Set<Integer> critical = new HashSet<>();
List<Integer> pseudoCritical = new ArrayList<>();
LinkedList<int[]> edges = new LinkedList<>();
for (int i = 0; i < oEdges.length; i++) {
edges.add(new int[] {oEdges[i][0], oEdges[i][1], oEdges[i][2], i});
}
// get original minMst
Collections.sort(edges, (a, b) -> a[2] - b[2]); // sort -> O(ElogE)
int minMst = getMst(edges, -1, n); // O(n*Akeman)
// critical means, if you remove this edge, mst will be larger, so test it
for (int i = 0; i < edges.size(); i++) { // O(E*n*Akeman)
int newMst = getMst(edges, i, n);
if (newMst > minMst) {
int oldIndex = edges.get(i)[3];
critical.add(oldIndex);
}
}
// pseudoCritical means, if you add this edge first, mst is still the same as original mst
for (int i = 0; i < edges.size(); i++) {
int oldIndex = edges.get(i)[3];
if (!critical.contains(oldIndex)) { // critical & pseudoCritical 是互斥的, 所以存在 critical 的必然不是 pseudoCritical
edges.addFirst(edges.get(i)); // 先加入這個邊看看
int newMst = getMst(edges, -1, n);
if (newMst == minMst) { // 看值是否會改變
pseudoCritical.add(oldIndex); // 不變就是 pseudoCritical
}
edges.removeFirst(); // 用完移掉
}
}
List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList<>(critical));
result.add(pseudoCritical);
return result;
}
public int getMst(LinkedList<int[]> edges, int ignoreEdge, int n) {
UnionFind uf = new UnionFind(n);
int mstWeight = 0;
for (int i = 0; i < edges.size(); i++) {
int[] edge = edges.get(i);
if (ignoreEdge == i) { // 不加邊
continue;
}
if (uf.union(edge[0], edge[1])) {
mstWeight += edge[2];
}
}
return uf.getCount() == 1 ? mstWeight : Integer.MAX_VALUE;
}
class UnionFind {
private int[] parent;
int count;
UnionFind(int n) {
this.count = n;
this.parent = new int[n];
for (int i = 0; i < n; i++) {
this.parent[i] = i;
}
}
public boolean union(int i, int j) {
int x = find(i);
int y = find(j);
if (x != y) {
this.parent[x] = y;
this.count--;
return true;
}
return false;
}
private int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
private int getCount() {
return this.count;
}
}
}
```
Last updated