Given a weighted undirected connected graph with n vertices numbered from 0 to n - 1, and an array edges where edges[i] = [ai, bi, weighti] represents a bidirectional and weighted edge between nodes ai and bi. A minimum spanning tree (MST) is a subset of the graph’s edges that connects all vertices without cycles and with the minimum possible total edge weight.
Find all the critical and pseudo-critical edges in the given graph’s minimum spanning tree (MST). An MST edge whose deletion from the graph would cause the MST weight to increase is called a critical edge. On the other hand, a pseudo-critical edge is that which can appear in some MSTs but not all.
Note that you can return the indices of the edges in any order.
Example 1:
Input: n = 5, edges = [[0,1,1],[1,2,1],[2,3,2],[0,3,2],[0,4,3],[3,4,3],[1,4,6]]
Output: [[0,1],[2,3,4,5]]
Explanation: The figure above describes the graph.
The following figure shows all the possible MSTs:
Notice that the two edges 0 and 1 appear in all MSTs, therefore they are critical edges, so we return them in the first list of the output.
The edges 2, 3, 4, and 5 are only part of some MSTs, therefore they are considered pseudo-critical edges. We add them to the second list of the output.
Example 2:
Input: n = 4, edges = [[0,1,1],[1,2,1],[2,3,1],[0,3,1]]
Output: [[],[0,1,2,3]]
Explanation: We can observe that since all 4 edges have equal weight, choosing any 3 edges from the given 4 will yield an MST. Therefore all 4 edges are pseudo-critical.
Constraints:
- 2 <= n <= 100
- 1 <= edges.length <= min(200, n * (n - 1) / 2)
- edges[i].length == 3
- 0 <= ai < bi < n
- 1 <= weighti <= 1000
- All pairs (ai, bi) are distinct.
用所有的 edges 建立 mst, 此时 mst 的 weight 我们记做 min_weight, 因为此时我们生成的 mst 的 weight 一定是最小的。
critical edge 的检查方法: 移除该 edge, 然后建立 mst, 如果 mst 的 weight > min_weight 则证明此 edge 是 critical edge
pseudo critical edge 的检查方法: 强制用该 edge 生成 mst, 如果生成的 mst 的 weight == min_weight 则此 edge 为 pseudo critical edge。其实换种方法理解就是该 edge 一定至少出现在一个 weight == min_weight 的 mst 中
impl Solution {
fn find(parents: &mut Vec<usize>, n: usize) -> usize {
if parents[n] == n {
return n;
}
let p = Solution::find(parents, parents[n]);
parents[n] = p;
p
}
fn union(parents: &mut Vec<usize>, a: usize, b: usize) {
let pa = Solution::find(parents, a);
let pb = Solution::find(parents, b);
parents[pa] = pb;
}
fn build_mst(n: i32, edges: &Vec<Vec<i32>>, pass: Option<usize>, must_included: Option<usize>) -> i32 {
let mut num_of_components = n;
let mut parents: Vec<usize> = (0..n as usize).into_iter().collect();
let mut weight = 0;
if let Some(i) = must_included {
Solution::union(&mut parents, edges[i][0] as usize, edges[i][1] as usize);
num_of_components -= 1;
weight += edges[i][2];
}
for (i, edge) in edges.into_iter().enumerate() {
if num_of_components == 1 {
break;
}
if let Some(j) = pass {
if i == j {
continue;
}
}
if Solution::find(&mut parents, edge[0] as usize) == Solution::find(&mut parents, edge[1] as usize) {
continue;
}
Solution::union(&mut parents, edge[0] as usize, edge[1] as usize);
num_of_components -= 1;
weight += edge[2];
}
if num_of_components > 1 {
i32::MAX
} else {
weight
}
}
pub fn find_critical_and_pseudo_critical_edges(n: i32, edges: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let mut edges: Vec<Vec<i32>> = edges
.into_iter()
.enumerate()
.map(|(i, mut l)| {
l.push(i as i32);
l
})
.collect();
edges.sort_by_key(|l| l[2]);
let min_weight = Solution::build_mst(n, &edges, None, None);
let mut critical_edges = Vec::new();
let mut pseudo_critical_edges = Vec::new();
for i in 0..edges.len() {
if min_weight < Solution::build_mst(n, &edges, Some(i), None) {
critical_edges.push(edges[i][3]);
continue;
}
if min_weight == Solution::build_mst(n, &edges, None, Some(i)) {
pseudo_critical_edges.push(edges[i][3]);
}
}
vec![critical_edges, pseudo_critical_edges]
}
}