Skip to main content

competitive/graph/
shortest_path.rs

1use super::*;
2use std::{
3    cmp::{Ordering, Reverse},
4    collections::{BinaryHeap, VecDeque},
5    marker::PhantomData,
6    ops::Add,
7};
8
9pub trait ShortestPathSemiRing {
10    type T: Clone + Ord;
11    fn source() -> Self::T;
12    fn inf() -> Self::T;
13    fn mul(x: &Self::T, y: &Self::T) -> Self::T;
14    fn add_assign(x: &mut Self::T, y: &Self::T) -> bool;
15}
16
17pub struct StandardSp<M>(PhantomData<fn() -> M>);
18impl<M> ShortestPathSemiRing for StandardSp<M>
19where
20    M: Monoid<T: Bounded + Ord>,
21{
22    type T = M::T;
23    #[inline]
24    fn source() -> Self::T {
25        M::unit()
26    }
27    #[inline]
28    fn inf() -> Self::T {
29        M::T::maximum()
30    }
31    #[inline]
32    fn mul(x: &Self::T, y: &Self::T) -> Self::T {
33        M::operate(x, y)
34    }
35    #[inline]
36    fn add_assign(x: &mut Self::T, y: &Self::T) -> bool {
37        if &*x > y {
38            *x = y.clone();
39            true
40        } else {
41            false
42        }
43    }
44}
45
46pub struct OptionSp<M>(PhantomData<fn() -> M>);
47impl<M> ShortestPathSemiRing for OptionSp<M>
48where
49    M: Monoid<T: Ord>,
50{
51    type T = Option<M::T>;
52    #[inline]
53    fn source() -> Self::T {
54        Some(M::unit())
55    }
56    #[inline]
57    fn inf() -> Self::T {
58        None
59    }
60    #[inline]
61    fn mul(x: &Self::T, y: &Self::T) -> Self::T {
62        match (x, y) {
63            (Some(x), Some(y)) => Some(M::operate(x, y)),
64            _ => None,
65        }
66    }
67    #[inline]
68    fn add_assign(x: &mut Self::T, y: &Self::T) -> bool {
69        if let Some(y) = y {
70            if let Some(x) = x {
71                if &*x > y {
72                    *x = y.clone();
73                    true
74                } else {
75                    false
76                }
77            } else {
78                *x = Some(y.clone());
79                true
80            }
81        } else {
82            false
83        }
84    }
85}
86
87pub struct PathFoldingSp<M, S>(PhantomData<fn() -> (M, S)>);
88impl<M, S> ShortestPathSemiRing for PathFoldingSp<M, S>
89where
90    M: Monoid<T: Bounded + Ord>,
91    S: SemiRing,
92{
93    type T = PartialIgnoredOrd<M::T, S::T>;
94    #[inline]
95    fn source() -> Self::T {
96        PartialIgnoredOrd(M::unit(), S::one())
97    }
98    #[inline]
99    fn inf() -> Self::T {
100        PartialIgnoredOrd(M::T::maximum(), S::zero())
101    }
102    #[inline]
103    fn mul(x: &Self::T, y: &Self::T) -> Self::T {
104        PartialIgnoredOrd(M::operate(&x.0, &y.0), S::mul(&x.1, &y.1))
105    }
106    #[inline]
107    fn add_assign(x: &mut Self::T, y: &Self::T) -> bool {
108        match x.0.cmp(&y.0) {
109            Ordering::Equal => {
110                x.1 = S::add(&x.1, &y.1);
111                false
112            }
113            Ordering::Greater => {
114                *x = y.clone();
115                true
116            }
117            _ => false,
118        }
119    }
120}
121
122pub trait ParentPolicy<G>
123where
124    G: Graph,
125{
126    type State;
127    fn init(graph: &G) -> Self::State;
128    fn save_parent(graph: &G, state: &mut Self::State, from: G::Vertex, to: G::Vertex);
129}
130
131pub enum NoParent {}
132impl<G> ParentPolicy<G> for NoParent
133where
134    G: Graph,
135{
136    type State = ();
137    fn init(_graph: &G) {}
138    fn save_parent(_graph: &G, _state: &mut Self::State, _from: G::Vertex, _to: G::Vertex) {}
139}
140
141pub struct RecordParent;
142impl<G> ParentPolicy<G> for RecordParent
143where
144    G: Graph + VertexMap<Option<<G as Graph>::Vertex>>,
145{
146    type State = <G as VertexMap<Option<<G as Graph>::Vertex>>>::Vmap;
147    fn init(graph: &G) -> Self::State {
148        graph.construct_vmap(|| None)
149    }
150    fn save_parent(graph: &G, state: &mut Self::State, from: G::Vertex, to: G::Vertex) {
151        *graph.vmap_get_mut(state, to) = Some(from);
152    }
153}
154
155pub struct ShortestPathWithParent<G, S, P = RecordParent>
156where
157    G: Graph + VertexMap<S::T>,
158    S: ShortestPathSemiRing,
159    P: ParentPolicy<G>,
160{
161    pub dist: <G as VertexMap<S::T>>::Vmap,
162    pub parent: P::State,
163}
164
165impl<G, S> ShortestPathWithParent<G, S, RecordParent>
166where
167    G: Graph + VertexMap<S::T> + VertexMap<Option<<G as Graph>::Vertex>>,
168    S: ShortestPathSemiRing,
169{
170    pub fn path_to(&self, graph: &G, target: G::Vertex) -> Option<Vec<G::Vertex>> {
171        let dist: &S::T = graph.vmap_get(&self.dist, target);
172        if dist == &S::inf() {
173            return None;
174        }
175        let mut cur = target;
176        let mut path = vec![cur];
177        while let &Some(p) = graph.vmap_get(&self.parent, cur) {
178            path.push(p);
179            cur = p;
180        }
181        path.reverse();
182        Some(path)
183    }
184}
185
186pub trait ShortestPathExt: Graph {
187    fn standard_sp<'a, M>(&'a self) -> ShortestPathBuilder<'a, Self, StandardSp<M>>
188    where
189        Self: Sized,
190        M: Monoid<T: Bounded + Ord>,
191    {
192        ShortestPathBuilder {
193            graph: self,
194            _marker: PhantomData,
195        }
196    }
197
198    fn standard_sp_additive<'a, T>(
199        &'a self,
200    ) -> ShortestPathBuilder<'a, Self, StandardSp<AdditiveOperation<T>>>
201    where
202        Self: Sized,
203        T: Clone + Zero + Add<Output = T> + Bounded + Ord,
204    {
205        ShortestPathBuilder {
206            graph: self,
207            _marker: PhantomData,
208        }
209    }
210
211    fn option_sp<'a, M>(&'a self) -> ShortestPathBuilder<'a, Self, OptionSp<M>>
212    where
213        Self: Sized,
214        M: Monoid<T: Ord>,
215    {
216        ShortestPathBuilder {
217            graph: self,
218            _marker: PhantomData,
219        }
220    }
221
222    fn option_sp_additive<'a, T>(
223        &'a self,
224    ) -> ShortestPathBuilder<'a, Self, OptionSp<AdditiveOperation<T>>>
225    where
226        Self: Sized,
227        T: Clone + Zero + Add<Output = T> + Ord,
228    {
229        ShortestPathBuilder {
230            graph: self,
231            _marker: PhantomData,
232        }
233    }
234
235    fn path_folding_sp<'a, M, S>(&'a self) -> ShortestPathBuilder<'a, Self, PathFoldingSp<M, S>>
236    where
237        Self: Sized,
238        M: Monoid<T: Bounded + Ord>,
239        S: SemiRing,
240    {
241        ShortestPathBuilder {
242            graph: self,
243            _marker: PhantomData,
244        }
245    }
246
247    fn path_folding_sp_additive_addmul<'a, T, U>(
248        &'a self,
249    ) -> ShortestPathBuilder<'a, Self, PathFoldingSp<AdditiveOperation<T>, AddMulOperation<U>>>
250    where
251        Self: Sized,
252        T: Clone + Zero + Add<Output = T> + Bounded + Ord,
253        U: DotProduct + One,
254    {
255        ShortestPathBuilder {
256            graph: self,
257            _marker: PhantomData,
258        }
259    }
260}
261impl<G> ShortestPathExt for G where G: Graph + ?Sized {}
262
263pub struct ShortestPathBuilder<'a, G, S, P = NoParent>
264where
265    G: Graph,
266    S: ShortestPathSemiRing,
267    P: ParentPolicy<G>,
268{
269    graph: &'a G,
270    _marker: PhantomData<fn() -> (S, P)>,
271}
272
273impl<'a, G, S, P> ShortestPathBuilder<'a, G, S, P>
274where
275    G: Graph,
276    S: ShortestPathSemiRing,
277    P: ParentPolicy<G>,
278{
279    fn bfs_distance_core<M, I>(&self, sources: I, weight: &M) -> ShortestPathWithParent<G, S, P>
280    where
281        G: VertexMap<S::T>,
282        M: Fn(G::Label) -> S::T + ?Sized,
283        I: IntoIterator<Item = G::Vertex>,
284    {
285        let graph = self.graph;
286        let mut dist = graph.construct_vmap(S::inf);
287        let mut parent = P::init(graph);
288        let mut deq = VecDeque::new();
289        for source in sources.into_iter() {
290            *graph.vmap_get_mut(&mut dist, source) = S::source();
291            deq.push_back(source);
292        }
293        let zero = S::source();
294        while let Some(u) = deq.pop_front() {
295            for neighbor in graph.neighbors(u) {
296                let v = neighbor.to;
297                let w = weight(neighbor.label);
298                let nd = S::mul(graph.vmap_get(&dist, u), &w);
299                if S::add_assign(graph.vmap_get_mut(&mut dist, v), &nd) {
300                    P::save_parent(graph, &mut parent, u, v);
301                    if w == zero {
302                        deq.push_front(v);
303                    } else {
304                        deq.push_back(v);
305                    }
306                }
307            }
308        }
309        ShortestPathWithParent { dist, parent }
310    }
311
312    fn dijkstra_core<M, I>(
313        &self,
314        sources: I,
315        weight: &M,
316        mut stop: impl FnMut(G::Vertex) -> bool,
317    ) -> ShortestPathWithParent<G, S, P>
318    where
319        G: VertexMap<S::T>,
320        M: Fn(G::Label) -> S::T + ?Sized,
321        I: IntoIterator<Item = G::Vertex>,
322    {
323        let graph = self.graph;
324        let mut dist = graph.construct_vmap(S::inf);
325        let mut parent = P::init(graph);
326        let mut heap = BinaryHeap::new();
327        for source in sources.into_iter() {
328            *graph.vmap_get_mut(&mut dist, source) = S::source();
329            heap.push(PartialIgnoredOrd(Reverse(S::source()), source));
330        }
331        while let Some(PartialIgnoredOrd(Reverse(d), u)) = heap.pop() {
332            let current = graph.vmap_get(&dist, u);
333            if current != &d {
334                continue;
335            }
336            if stop(u) {
337                break;
338            }
339            let d = current.clone();
340            for neighbor in graph.neighbors(u) {
341                let v = neighbor.to;
342                let weight = weight(neighbor.label);
343                let nd = S::mul(&d, &weight);
344                if S::add_assign(graph.vmap_get_mut(&mut dist, v), &nd) {
345                    P::save_parent(graph, &mut parent, u, v);
346                    heap.push(PartialIgnoredOrd(Reverse(nd), v));
347                }
348            }
349        }
350        ShortestPathWithParent { dist, parent }
351    }
352
353    fn bellman_ford_core<M, I>(
354        &self,
355        sources: I,
356        weight: &M,
357        check: bool,
358    ) -> Option<ShortestPathWithParent<G, S, P>>
359    where
360        G: VertexMap<S::T>,
361        M: Fn(G::Label) -> S::T + ?Sized,
362        I: IntoIterator<Item = G::Vertex>,
363        P: ParentPolicy<G>,
364    {
365        let graph = self.graph;
366        let mut dist = graph.construct_vmap(S::inf);
367        let mut parent = P::init(graph);
368        for source in sources.into_iter() {
369            *graph.vmap_get_mut(&mut dist, source) = S::source();
370        }
371        let vsize = graph.vsize();
372        for _ in 1..vsize {
373            let mut updated = false;
374            for u in graph.vertices() {
375                for neighbor in graph.neighbors(u) {
376                    let v = neighbor.to;
377                    let weight = weight(neighbor.label);
378                    let nd = S::mul(graph.vmap_get(&dist, u), &weight);
379                    if S::add_assign(graph.vmap_get_mut(&mut dist, v), &nd) {
380                        P::save_parent(graph, &mut parent, u, v);
381                        updated = true;
382                    }
383                }
384            }
385            if !updated {
386                break;
387            }
388        }
389        if check {
390            for u in graph.vertices() {
391                for neighbor in graph.neighbors(u) {
392                    let v = neighbor.to;
393                    let weight = weight(neighbor.label);
394                    let nd = S::mul(graph.vmap_get(&dist, u), &weight);
395                    if S::add_assign(graph.vmap_get_mut(&mut dist, v), &nd) {
396                        return None;
397                    }
398                }
399            }
400        }
401        Some(ShortestPathWithParent { dist, parent })
402    }
403}
404
405impl<'a, G, S> ShortestPathBuilder<'a, G, S, NoParent>
406where
407    G: Graph,
408    S: ShortestPathSemiRing,
409{
410    pub fn with_parent(self) -> ShortestPathBuilder<'a, G, S, RecordParent>
411    where
412        G: VertexMap<Option<<G as Graph>::Vertex>>,
413    {
414        ShortestPathBuilder {
415            graph: self.graph,
416            _marker: PhantomData,
417        }
418    }
419
420    pub fn bfs_distance<M, I>(&self, sources: I, weight: M) -> <G as VertexMap<S::T>>::Vmap
421    where
422        G: VertexMap<S::T>,
423        M: Fn(G::Label) -> S::T,
424        I: IntoIterator<Item = G::Vertex>,
425    {
426        self.bfs_distance_core(sources, &weight).dist
427    }
428
429    pub fn dijkstra<M, I>(&self, sources: I, weight: M) -> <G as VertexMap<S::T>>::Vmap
430    where
431        G: VertexMap<S::T>,
432        M: Fn(G::Label) -> S::T,
433        I: IntoIterator<Item = G::Vertex>,
434    {
435        self.dijkstra_core(sources, &weight, |_| false).dist
436    }
437
438    pub fn bellman_ford<M, I>(
439        &self,
440        sources: I,
441        weight: M,
442        check: bool,
443    ) -> Option<<G as VertexMap<S::T>>::Vmap>
444    where
445        G: VertexMap<S::T>,
446        M: Fn(G::Label) -> S::T,
447        I: IntoIterator<Item = G::Vertex>,
448    {
449        self.bellman_ford_core(sources, &weight, check)
450            .map(|sp| sp.dist)
451    }
452
453    pub fn warshall_floyd_ap<M>(
454        &self,
455        weight: M,
456    ) -> <G as VertexMap<<G as VertexMap<S::T>>::Vmap>>::Vmap
457    where
458        G: VertexMap<S::T, Vmap: Clone> + VertexMap<<G as VertexMap<S::T>>::Vmap>,
459        M: Fn(G::Label) -> S::T,
460    {
461        let graph = self.graph;
462        let mut dist = graph.construct_vmap(|| graph.construct_vmap(S::inf));
463        for u in graph.vertices() {
464            *graph.vmap_get_mut(graph.vmap_get_mut(&mut dist, u), u) = S::source();
465        }
466        for u in graph.vertices() {
467            for neighbor in graph.neighbors(u) {
468                let weight = weight(neighbor.label);
469                S::add_assign(
470                    graph.vmap_get_mut(graph.vmap_get_mut(&mut dist, u), neighbor.to),
471                    &weight,
472                );
473            }
474        }
475        for k in graph.vertices() {
476            for i in graph.vertices() {
477                for j in graph.vertices() {
478                    let d1 = graph.vmap_get(graph.vmap_get(&dist, i), k);
479                    let d2 = graph.vmap_get(graph.vmap_get(&dist, k), j);
480                    let nd = S::mul(d1, d2);
481                    S::add_assign(graph.vmap_get_mut(graph.vmap_get_mut(&mut dist, i), j), &nd);
482                }
483            }
484        }
485        dist
486    }
487}
488
489impl<'a, G, S> ShortestPathBuilder<'a, G, S, RecordParent>
490where
491    G: Graph + VertexMap<Option<<G as Graph>::Vertex>>,
492    S: ShortestPathSemiRing,
493{
494    pub fn bfs_distance<M, I>(&self, sources: I, weight: M) -> ShortestPathWithParent<G, S>
495    where
496        G: VertexMap<S::T>,
497        M: Fn(G::Label) -> S::T,
498        I: IntoIterator<Item = G::Vertex>,
499    {
500        self.bfs_distance_core(sources, &weight)
501    }
502
503    pub fn dijkstra<M, I>(&self, sources: I, weight: M) -> ShortestPathWithParent<G, S>
504    where
505        G: VertexMap<S::T>,
506        M: Fn(G::Label) -> S::T,
507        I: IntoIterator<Item = G::Vertex>,
508    {
509        self.dijkstra_core(sources, &weight, |_| false)
510    }
511
512    pub fn bellman_ford<M, I>(
513        &self,
514        sources: I,
515        weight: M,
516        check: bool,
517    ) -> Option<ShortestPathWithParent<G, S>>
518    where
519        G: VertexMap<S::T>,
520        M: Fn(G::Label) -> S::T,
521        I: IntoIterator<Item = G::Vertex>,
522    {
523        self.bellman_ford_core(sources, &weight, check)
524    }
525}
526
527impl<'a, G, M, P> ShortestPathBuilder<'a, G, StandardSp<M>, P>
528where
529    G: Graph,
530    M: Monoid<T: Bounded + Ord>,
531    P: ParentPolicy<G>,
532{
533    /// Distances other than the target may remain tentative.
534    pub fn dijkstra_to<W, I>(
535        &self,
536        sources: I,
537        target: G::Vertex,
538        weight: W,
539    ) -> ShortestPathWithParent<G, StandardSp<M>, P>
540    where
541        G: VertexMap<M::T>,
542        W: Fn(G::Label) -> M::T,
543        I: IntoIterator<Item = G::Vertex>,
544    {
545        self.dijkstra_core(sources, &weight, |u| u == target)
546    }
547}
548
549#[cfg(test)]
550mod tests {
551    use super::*;
552    use crate::{
553        num::Saturating,
554        rand,
555        tools::{PartialOrdExt, Xorshift},
556    };
557    use std::collections::HashMap;
558
559    #[test]
560    fn test_shortest_path() {
561        struct Label(usize);
562
563        let mut rng = Xorshift::default();
564        for _ in 0..100 {
565            rand!(rng, n: 1..30, m: 0..80, edges: [(0..n, 0..n); m], w: [0..100_000i64; m]);
566            let g = DirectedSparseGraph::from_edges(n, edges.clone());
567            let closure = UsizeGraph::new(n, |u| {
568                edges
569                    .iter()
570                    .enumerate()
571                    .filter(move |&(_, &(from, _))| from == u)
572                    .map(|(eid, &(_, to))| (to, Label(eid)))
573            });
574            let weight: &dyn Fn(usize) -> Option<i64> = &|eid| Some(w[eid]);
575            let dijkstra: Vec<_> = (0..n)
576                .map(|src| g.option_sp_additive().dijkstra([src], weight))
577                .collect();
578            let closure_dijkstra: Vec<_> = (0..n)
579                .map(|src| {
580                    closure
581                        .option_sp_additive()
582                        .dijkstra([src], |label| Some(w[label.0]))
583                })
584                .collect();
585            let bellman_ford: Vec<_> = (0..n)
586                .map(|src| {
587                    g.option_sp_additive()
588                        .bellman_ford([src], |eid| Some(w[eid]), false)
589                        .unwrap()
590                })
591                .collect();
592            let warshall_floyd = g.option_sp_additive().warshall_floyd_ap(|eid| Some(w[eid]));
593            assert_eq!(dijkstra, closure_dijkstra);
594            assert_eq!(dijkstra, bellman_ford);
595            assert_eq!(dijkstra, warshall_floyd);
596            for (target, (&first, &last)) in dijkstra[0].iter().zip(&dijkstra[n - 1]).enumerate() {
597                let point = g
598                    .standard_sp_additive()
599                    .dijkstra_to([0, n - 1], target, |eid| w[eid] as u64);
600                let expected = [first, last]
601                    .into_iter()
602                    .flatten()
603                    .min()
604                    .map_or(u64::MAX, |distance| distance as u64);
605                assert_eq!(point.dist[target], expected);
606            }
607        }
608    }
609
610    #[test]
611    fn test_spfa() {
612        let mut rng = Xorshift::default();
613        for _ in 0..100 {
614            rand!(rng, n: 1..100, m: 1..200, edges: [(0..n, 0..n); m], ub: 0..=1i64, w: [0..=ub * 100_000i64; m]);
615            let g = DirectedSparseGraph::from_edges(n, edges);
616            let bfs: Vec<_> = (0..n)
617                .map(|src| {
618                    g.option_sp_additive()
619                        .bfs_distance([src], |eid| Some(w[eid]))
620                })
621                .collect();
622            let warshall_floyd = g.option_sp_additive().warshall_floyd_ap(|eid| Some(w[eid]));
623            assert_eq!(bfs, warshall_floyd);
624        }
625    }
626
627    #[test]
628    fn test_shortest_path_with_parent() {
629        let mut rng = Xorshift::default();
630        for _ in 0..100 {
631            rand!(rng, n: 1..100, m: 1..200, edges: [(0..n, 0..n); m], ub: 0..=1i64, w: [0..=ub * 100_000i64; m]);
632            let mut cost: HashMap<_, _> = HashMap::new();
633            for (&(u, v), &w) in edges.iter().zip(w.iter()) {
634                cost.entry((u, v)).or_insert(w).chmin(w);
635            }
636            let g = DirectedSparseGraph::from_edges(n, edges);
637            for src in 0..n {
638                let bfs = g
639                    .option_sp_additive()
640                    .with_parent()
641                    .bfs_distance([src], |eid| Some(w[eid]));
642                let dijkstra = g
643                    .option_sp_additive()
644                    .with_parent()
645                    .dijkstra([src], |eid| Some(w[eid]));
646                let bellman_ford = g
647                    .option_sp_additive()
648                    .with_parent()
649                    .bellman_ford([src], |eid| Some(w[eid]), false)
650                    .unwrap();
651                let dist = g.option_sp_additive().dijkstra([src], |eid| Some(w[eid]));
652                assert_eq!(bfs.dist, dist);
653                assert_eq!(dijkstra.dist, dist);
654                assert_eq!(bellman_ford.dist, dist);
655                for (target, &dist) in dist.iter().enumerate() {
656                    let point =
657                        g.standard_sp_additive()
658                            .with_parent()
659                            .dijkstra_to([src], target, |eid| w[eid] as u64);
660                    assert_eq!(
661                        point.dist[target],
662                        dist.map_or(u64::MAX, |distance| distance as u64)
663                    );
664                    let path = point.path_to(&g, target);
665                    assert_eq!(path.is_some(), dist.is_some());
666                    if let Some(path) = path {
667                        assert_eq!(path.first(), Some(&src));
668                        assert_eq!(path.last(), Some(&target));
669                        assert_eq!(
670                            point.dist[target],
671                            path.windows(2).map(|w| cost[&(w[0], w[1])] as u64).sum()
672                        );
673                    }
674                    match dist {
675                        None => {
676                            assert!(bfs.path_to(&g, target).is_none());
677                            assert!(dijkstra.path_to(&g, target).is_none());
678                            assert!(bellman_ford.path_to(&g, target).is_none());
679                        }
680                        Some(dist) => {
681                            let path_bfs = bfs.path_to(&g, target).unwrap();
682                            assert_eq!(*path_bfs.first().unwrap(), src);
683                            assert_eq!(*path_bfs.last().unwrap(), target);
684                            assert_eq!(
685                                path_bfs
686                                    .windows(2)
687                                    .map(|w| cost[&(w[0], w[1])])
688                                    .sum::<i64>(),
689                                dist
690                            );
691                            let path_dijkstra = dijkstra.path_to(&g, target).unwrap();
692                            assert_eq!(*path_dijkstra.first().unwrap(), src);
693                            assert_eq!(*path_dijkstra.last().unwrap(), target);
694                            assert_eq!(
695                                path_dijkstra
696                                    .windows(2)
697                                    .map(|w| cost[&(w[0], w[1])])
698                                    .sum::<i64>(),
699                                dist
700                            );
701                            let path_bellman_ford = bellman_ford.path_to(&g, target).unwrap();
702                            assert_eq!(*path_bellman_ford.first().unwrap(), src);
703                            assert_eq!(*path_bellman_ford.last().unwrap(), target);
704                            assert_eq!(
705                                path_bellman_ford
706                                    .windows(2)
707                                    .map(|w| cost[&(w[0], w[1])])
708                                    .sum::<i64>(),
709                                dist
710                            );
711                        }
712                    }
713                }
714            }
715        }
716    }
717
718    #[test]
719    fn test_path_folding() {
720        const N: usize = 5;
721        for n in 1..=N {
722            let all_edges: Vec<_> = (0..n)
723                .flat_map(|u| (u + 1..n).map(move |v| (u, v)))
724                .collect();
725            for bits in 0..1 << all_edges.len() {
726                let edges: Vec<_> = all_edges
727                    .iter()
728                    .enumerate()
729                    .filter_map(|(eid, &edge)| ((bits >> eid) & 1 == 1).then_some(edge))
730                    .collect();
731                let graph = DirectedSparseGraph::from_edges(n, edges.clone());
732                for src in 0..n {
733                    let mut expected = vec![(usize::MAX, 0u64); n];
734                    expected[src] = (0, 1);
735                    for u in 0..n {
736                        if expected[u].0 == usize::MAX {
737                            continue;
738                        }
739                        for &(_, v) in edges.iter().filter(|&&(from, _)| from == u) {
740                            let nd = expected[u].0 + 1;
741                            if nd < expected[v].0 {
742                                expected[v] = (nd, expected[u].1);
743                            } else if nd == expected[v].0 {
744                                expected[v].1 += expected[u].1;
745                            }
746                        }
747                    }
748                    let actual = graph
749                        .path_folding_sp_additive_addmul()
750                        .dijkstra([src], |_| PartialIgnoredOrd(Saturating(1usize), 1u64));
751                    for (actual, expected) in actual.iter().zip(expected) {
752                        assert_eq!(actual.0, Saturating(expected.0));
753                        assert_eq!(actual.1, expected.1);
754                    }
755                }
756            }
757        }
758
759        let mut rng = Xorshift::default();
760        for _ in 0..1000 {
761            let n = rng.random(1..=12);
762            let mut edges = Vec::new();
763            for u in 0..n {
764                for v in u + 1..n {
765                    if rng.random(0..2) == 0 {
766                        edges.push((u, v));
767                    }
768                }
769            }
770            let weights: Vec<usize> = rng.random_iter(1..=10).take(edges.len()).collect();
771            let graph = DirectedSparseGraph::from_edges(n, edges.clone());
772            let src = rng.random(0..n);
773            let mut paths = vec![(src, 0)];
774            let mut expected = vec![(usize::MAX, 0u64); n];
775            while let Some((u, distance)) = paths.pop() {
776                if distance < expected[u].0 {
777                    expected[u] = (distance, 1);
778                } else if distance == expected[u].0 {
779                    expected[u].1 += 1;
780                }
781                for (eid, &(_, v)) in edges
782                    .iter()
783                    .enumerate()
784                    .filter(|&(_, &(from, _))| from == u)
785                {
786                    paths.push((v, distance + weights[eid]));
787                }
788            }
789            let actual = graph
790                .path_folding_sp_additive_addmul()
791                .dijkstra([src], |eid| {
792                    PartialIgnoredOrd(Saturating(weights[eid]), 1u64)
793                });
794            for (actual, expected) in actual.iter().zip(expected) {
795                assert_eq!(actual.0, Saturating(expected.0));
796                assert_eq!(actual.1, expected.1);
797            }
798        }
799    }
800}