Kimi LeetCode 3812. 翻转树上最少边 Rust实现
这是 LeetCode 3812 翻转树上最少边(Minimum Edge Toggles on a Tree)的 Rust 实现。
解题思路
核心观察:翻转一条边会同时改变其两个端点的颜色(0↔1)。每条边最多翻转一次。
自底向上 DFS:对于每个节点,若其子树返回需要翻转,则翻转该边,同时当前节点的翻转状态也被取反。最终根节点必须不需要翻转,否则无解。
Rust 实现
```rust
use std::collections::HashMap;
impl Solution {
pub fn minimum_flips(n: i32, edges: Vec<Vec<i32>>, start: String, target: String) -> Vec<i32> {
let n = n as usize;
let start: Vec<char> = start.chars().collect();
let target: Vec<char> = target.chars().collect();
// 构建邻接表: 节点 -> [(邻居, 边索引)]
let mut g: Vec<Vec<(usize, usize)>> = vec![vec![]; n];
for (i, edge) in edges.iter().enumerate() {
let a = edge[0] as usize;
let b = edge[1] as usize;
g[a].push((b, i));
g[b].push((a, i));
}
let mut ans: Vec<usize> = Vec::new();
// DFS 返回节点 a 当前是否需要被翻转
fn dfs(
a: usize,
fa: i32,
g: &Vec<Vec<(usize, usize)>>,
start: &Vec<char>,
target: &Vec<char>,
ans: &mut Vec<usize>,
) -> bool {
let mut rev = start[a] != target[a];
for &(b, i) in &g[a] {
if b as i32 == fa {
continue;
}
// 如果子树需要翻转边 (a,b)
if dfs(b, a as i32, g, start, target, ans) {
ans.push(i); // 翻转这条边
rev = !rev; // 节点 a 的颜色也被翻转
}
}
rev
}
// 如果根节点还需要翻转,说明无解
if dfs(0, -1, &g, &start, &target, &mut ans) {
return vec![-1];
}
// 升序排序并转换为 i32
ans.sort();
ans.into_iter().map(|x| x as i32).collect()
}
}
```
复杂度
- 时间:O(n \log n),DFS 遍历 O(n),排序 O(n \log n)
- 空间:O(n),邻接表 + 递归栈
关键说明
要点 说明
`rev = start[a] != target[a]` 节点 `a` 当前是否需要被翻转
`dfs(b, a, ...)` 返回 `true` 子节点 `b` 需要被翻转,必须通过翻转边 `(a,b)` 解决
`rev = !rev` 翻转边后,节点 `a` 的颜色也被改变
根节点返回 `true` → `[-1]` 根没有父边,无法被翻转,说明无解
每条边最多翻转一次 翻转两次等于没翻,所以方案唯一且最短
更多推荐

所有评论(0)