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 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}