[a, b]
表示 a
比 b
更有钱.
i
钱少的中, 最安静的, 全局最有钱的答案对应其自身. [a, b]
为b -> a
, 则找到哪个出度为0, 则对应为最有钱的. 处理掉这个最有钱的后, 将b
的出度减一,
这时如果b
的出度变为了0, 那么b
就变为了此时最富的, 再重复处理
处理的过程: 看是不是之前有比它更有钱的,
如果有, 从中找出最安静的那个
pub fn loud_and_rich(richer: Vec<Vec<i32>>, quiet: Vec<i32>) -> Vec<i32> {
use std::collections::{HashMap, HashSet, VecDeque};
let mut out = vec![0; quiet.len()];
let mut oout = HashMap::new();
let mut iin = HashMap::new();
for rich in richer {
let (to, from) = (rich[0] as usize, rich[1] as usize);
out[from] += 1;
iin.entry(to).or_insert(HashSet::new()).insert(from);
oout.entry(from).or_insert(HashSet::new()).insert(to);
}
let mut queue = VecDeque::new();
for (idx, &cnt) in out.iter().enumerate() {
if cnt == 0 {
queue.push_back(idx); // 这点起始就是最富
}
}
let mut ans = vec![0; quiet.len()];
while !queue.is_empty() {
let sz = queue.len();
for _ in 0..sz {
let rich = queue.pop_front().unwrap();
// rich 是当前最富的, 但不一定是全局最富的,
// 因此检查其指向谁, 然后取下一个节点, 和其ans中的最安静的那个
let (mut most, mut qu) = (rich, quiet[rich]);
for &node in oout.get(&rich).unwrap_or(&HashSet::new()) {
if quiet[node] < qu {
most = node;
qu = quiet[node];
}
let node_ans = ans[node] as usize;
if quiet[node_ans] < qu {
most = node_ans;
qu = quiet[node_ans];
}
}
ans[rich] = most as i32;
// 将指向 rich 的节点, 出度都减1
for &node in iin.get(&rich).unwrap_or(&HashSet::new()) {
out[node] -= 1;
if out[node] == 0 {
queue.push_back(node); // 出度为0, 下一轮的最富
}
}
}
}
ans
}
graph
记录谁比 i
更穷(直接) pub fn loud_and_rich(richer: Vec<Vec<i32>>, quiet: Vec<i32>) -> Vec<i32> {
use std::collections::VecDeque;
let mut graph = vec![vec![]; quiet.len()];
let mut in_deg = vec![0; quiet.len()];
for r in richer {
let (rich, poor) = (r[0] as usize, r[1] as usize);
graph[rich].push(poor); // 记录谁比它穷
in_deg[poor] += 1; // 入度为0的, 为最富的
}
let mut ans = (0..quiet.len() as i32).collect::<Vec<i32>>(); // 先用自身填位
let mut queue = VecDeque::new();
for (idx, &ii) in in_deg.iter().enumerate() {
if ii == 0 {
queue.push_back(idx);
}
}
while !queue.is_empty() {
let rich = queue.pop_front().unwrap();
// 先计算更富有的, 全局最富有的, 其最终答案就是它自身
let ans_rich = ans[rich] as usize;
for &poor in graph.get(rich).unwrap() {
// 计算出富有的之后, 更新比它穷的
let ans_poor = ans[poor] as usize;
if quiet[ans_rich] < quiet[ans_poor] {
ans[poor] = ans_rich as i32;
}
// 从这个 rich 到 这个 poor 已经检查过了
// 后面不用在检查了, 因此对poor来说, 入度减1
in_deg[poor] -= 1;
if in_deg[poor] == 0 {
// 这时poor已经没有入度, 因此升级为最富有的
queue.push_back(poor);
}
}
}
ans
}
graph
记录谁比 i
更富有(直接) i
富有的得到答案后, 更新 i
对应的答案, 可能的答案有 i
i
富有的节点的答案 i
富有(直接)的节点可能不止一个, 因此需要都检查一下 pub fn loud_and_rich(richer: Vec<Vec<i32>>, quiet: Vec<i32>) -> Vec<i32> {
let mut graph = vec![vec![]; quiet.len()];
for r in richer {
let (to, from) = (r[0] as usize, r[1] as usize);
graph[from].push(to); // to 是 比 from 富有的
}
fn dfs(ans: &mut Vec<i32>, graph: &Vec<Vec<usize>>, quiet: &Vec<i32>, x: usize) {
if ans[x] != -1 {
// 已经判出结果的, 不用重复判
// 不论结果是啥, 因为dfs后有更新的逻辑
// 所以只要有结果, 那就是最终答案
return;
}
ans[x] = x as i32; // 用自身填位先
for &y in graph.get(x).unwrap() {
dfs(ans, graph, quiet, y);
// 比x富有的答案
let ans_x = ans[x] as usize;
// 比x富有的的y的最终答案,
// 由于是先执行的dfs, 因此这里已经拿到相对富有的y的最终答案
let ans_y = ans[y] as usize;
if quiet[ans_y] < quiet[ans_x] {
ans[x] = ans[y]; // 比x富有的y, 有比当前结果更安静的
}
}
}
let mut ans = vec![-1; quiet.len()];
for i in 0..quiet.len() {
// 都尝试一遍, 因为不定哪个最富, 哪个最穷
dfs(&mut ans, &graph, &quiet, i);
}
ans
}