haar_lib/graph/
matrix_tree.rs1use crate::graph::*;
7use crate::linalg::mod_p::determinant::*;
8use crate::math::prime_mod::PrimeMod;
9use crate::num::const_modint::*;
10
11pub fn count_undirected_spanning_tree<P: PrimeMod>(
13 g: &Graph<Undirected, impl EdgeTrait>,
14) -> ConstModInt<P> {
15 let modulo = ConstModIntBuilder::<P>::new();
16
17 let n = g.len();
18 let mut lap = vec![vec![modulo.from_u64(0); n - 1]; n - 1];
19
20 for e in g.nodes_iter().flatten() {
21 let from = e.from();
22 let to = e.to();
23
24 if from < n - 1 {
25 lap[from][from] += modulo.from_u64(1);
26 if to < n - 1 {
27 lap[from][to] -= modulo.from_u64(1);
28 }
29 }
30 }
31
32 determinant(lap, &modulo)
33}
34
35pub fn count_directed_spanning_tree<P: PrimeMod>(
37 g: &Graph<Directed, impl EdgeTrait>,
38 root: usize,
39) -> ConstModInt<P> {
40 let modulo = ConstModIntBuilder::<P>::new();
41
42 let n = g.len();
43 let mut lap = vec![vec![modulo.from_u64(0); n - 1]; n - 1];
44
45 for e in g.nodes_iter().flatten() {
46 let mut from = e.from();
47 let mut to = e.to();
48
49 if from == root {
50 continue;
51 }
52 if from > root {
53 from -= 1;
54 }
55 lap[from][from] += modulo.from_u64(1);
56
57 if to == root {
58 continue;
59 }
60 if to > root {
61 to -= 1;
62 }
63 lap[from][to] -= modulo.from_u64(1);
64 }
65
66 determinant(lap, &modulo)
67}