E - Transitivity Editorial
by
ngtkana
公式解説よりも漸近的に遅い解法ですが、実行時間には余裕で間に合うため、ご紹介です。
Floyd–Warshall のアルゴリズムにより推移閉包を計算すると \(O ( N ^ 3 )\) 時間で計算できますが、これを bitset (AtCoder では FixedBitSet
というクレートが使えます。)で高速化すると、\(O ( N ^ 3 / w )\) 時間(\(w\) はワードサイズ)となります。
use fixedbitset::FixedBitSet;
use proconio::{input, marker::Usize1};
fn main() {
input! {
n: usize,
m: usize,
edges: [(Usize1, Usize1); m],
}
let mut trans = vec![FixedBitSet::with_capacity(n); n];
(0..n).for_each(|i| trans[i].insert(i));
for &(i, j) in &edges {
trans[i].insert(j);
}
for j in 0..n {
for i in 0..n {
if trans[i][j] {
let x = trans[j].clone();
trans[i] |= x;
}
}
}
let ans = trans.iter().map(|row| row.count_ones(..)).sum::<usize>() - m - n;
println!("{}", ans);
}
posted:
last update: