1use std::collections::{BinaryHeap, HashSet, VecDeque};
6
7#[allow(dead_code)]
12pub struct TuttePolynomialEval {
13 edges: Vec<(usize, usize)>,
15 n: usize,
17}
18#[allow(dead_code)]
19impl TuttePolynomialEval {
20 pub fn from_graph(graph: &UndirectedGraph) -> Self {
22 let mut edges = Vec::new();
23 for u in 0..graph.n {
24 for &v in &graph.adj[u] {
25 if u < v {
26 edges.push((u, v));
27 }
28 }
29 }
30 Self { edges, n: graph.n }
31 }
32 pub fn evaluate(&self, x: f64, y: f64) -> f64 {
35 self.tutte_rec(&self.edges.clone(), self.n, x, y)
36 }
37 fn components(n: usize, edges: &[(usize, usize)]) -> usize {
38 let max_v = edges.iter().flat_map(|&(u, v)| [u, v]).max().unwrap_or(0);
39 let sz = max_v.max(n.saturating_sub(1)) + 1;
40 let mut parent: Vec<usize> = (0..sz).collect();
41 fn find(parent: &mut Vec<usize>, a: usize) -> usize {
42 if parent[a] != a {
43 parent[a] = find(parent, parent[a]);
44 }
45 parent[a]
46 }
47 for &(u, v) in edges {
48 if u == v {
49 continue;
50 }
51 let ru = find(&mut parent, u);
52 let rv = find(&mut parent, v);
53 if ru != rv {
54 parent[ru] = rv;
55 }
56 }
57 let count_n = n.min(sz);
58 (0..count_n).filter(|&i| find(&mut parent, i) == i).count()
59 }
60 fn vertex_count(edges: &[(usize, usize)], base_n: usize) -> usize {
62 let mut seen: HashSet<usize> = HashSet::new();
63 for &(u, v) in edges {
64 seen.insert(u);
65 seen.insert(v);
66 }
67 seen.len().max(base_n)
68 }
69 fn tutte_rec(&self, edges: &[(usize, usize)], n: usize, x: f64, y: f64) -> f64 {
70 if edges.is_empty() {
71 return x.powi((n as i32) - 1);
72 }
73 let e = edges[0];
74 let rest: Vec<(usize, usize)> = edges[1..].to_vec();
75 let is_loop = e.0 == e.1;
76 if is_loop {
77 return y * self.tutte_rec(&rest, n, x, y);
78 }
79 let c_with = Self::components(n, edges);
80 let c_without = Self::components(n, &rest);
81 let is_bridge = c_without > c_with;
82 if is_bridge {
83 let contracted = self.contract_edge(&rest, e);
84 let new_n = n.saturating_sub(1).max(1);
85 return x * self.tutte_rec(&contracted, new_n, x, y);
86 }
87 let contracted = self.contract_edge(&rest, e);
88 let new_n = n.saturating_sub(1).max(1);
89 let del = self.tutte_rec(&rest, n, x, y);
90 let con = self.tutte_rec(&contracted, new_n, x, y);
91 del + con
92 }
93 fn contract_edge(&self, edges: &[(usize, usize)], e: (usize, usize)) -> Vec<(usize, usize)> {
95 let (u, v) = e;
96 edges
97 .iter()
98 .map(|&(a, b)| {
99 let a2 = if a == v { u } else { a };
100 let b2 = if b == v { u } else { b };
101 (a2, b2)
102 })
103 .collect()
104 }
105}
106#[allow(dead_code)]
112pub struct SzemerédiRegularityLemma {
113 pub graph: UndirectedGraph,
115 pub epsilon: f64,
117}
118#[allow(dead_code)]
119impl SzemerédiRegularityLemma {
120 pub fn new(graph: UndirectedGraph, epsilon: f64) -> Self {
122 Self { graph, epsilon }
123 }
124 pub fn density(&self, a: &[usize], b: &[usize]) -> f64 {
126 let b_set: HashSet<usize> = b.iter().copied().collect();
127 let edges: usize = a
128 .iter()
129 .map(|&u| {
130 self.graph.adj[u]
131 .iter()
132 .filter(|v| b_set.contains(*v))
133 .count()
134 })
135 .sum();
136 let denom = a.len() * b.len();
137 if denom == 0 {
138 0.0
139 } else {
140 edges as f64 / denom as f64
141 }
142 }
143 pub fn is_regular_pair(&self, a: &[usize], b: &[usize]) -> bool {
147 let d = self.density(a, b);
148 let a_half: Vec<usize> = a[..a.len() / 2].to_vec();
149 let b_half: Vec<usize> = b[..b.len() / 2].to_vec();
150 let d_sub = self.density(&a_half, &b_half);
151 (d - d_sub).abs() <= self.epsilon
152 }
153 pub fn partition(&self, k: usize) -> Vec<Vec<usize>> {
155 let n = self.graph.n;
156 let k = k.max(1);
157 let mut parts: Vec<Vec<usize>> = vec![vec![]; k];
158 for v in 0..n {
159 parts[v % k].push(v);
160 }
161 parts
162 }
163 pub fn run(&self, k: usize) -> (Vec<Vec<usize>>, usize) {
166 let parts = self.partition(k);
167 let mut regular_pairs = 0usize;
168 for i in 0..parts.len() {
169 for j in (i + 1)..parts.len() {
170 if self.is_regular_pair(&parts[i], &parts[j]) {
171 regular_pairs += 1;
172 }
173 }
174 }
175 (parts, regular_pairs)
176 }
177}
178#[allow(dead_code)]
183pub struct TreewidthHeuristic {
184 adj: Vec<HashSet<usize>>,
186 n: usize,
188}
189#[allow(dead_code)]
190impl TreewidthHeuristic {
191 pub fn new(graph: &UndirectedGraph) -> Self {
193 Self {
194 adj: graph.adj.clone(),
195 n: graph.n,
196 }
197 }
198 fn fill_count(&self, v: usize) -> usize {
200 let neighbors: Vec<usize> = self.adj[v].iter().copied().collect();
201 let mut fill = 0usize;
202 for i in 0..neighbors.len() {
203 for j in (i + 1)..neighbors.len() {
204 let a = neighbors[i];
205 let b = neighbors[j];
206 if !self.adj[a].contains(&b) {
207 fill += 1;
208 }
209 }
210 }
211 fill
212 }
213 pub fn run(&mut self) -> (Vec<usize>, usize) {
215 let mut eliminated = vec![false; self.n];
216 let mut order = Vec::with_capacity(self.n);
217 let mut tw_bound = 0usize;
218 for _ in 0..self.n {
219 let v = (0..self.n)
220 .filter(|&u| !eliminated[u])
221 .min_by_key(|&u| self.fill_count(u))
222 .expect(
223 "at least one non-eliminated vertex exists: loop runs n times for n vertices",
224 );
225 let deg = self.adj[v].len();
226 tw_bound = tw_bound.max(deg);
227 let neighbors: Vec<usize> = self.adj[v].iter().copied().collect();
228 for i in 0..neighbors.len() {
229 for j in (i + 1)..neighbors.len() {
230 let a = neighbors[i];
231 let b = neighbors[j];
232 if a != b {
233 self.adj[a].insert(b);
234 self.adj[b].insert(a);
235 }
236 }
237 }
238 for &u in &neighbors {
239 self.adj[u].remove(&v);
240 }
241 self.adj[v].clear();
242 eliminated[v] = true;
243 order.push(v);
244 }
245 (order, tw_bound)
246 }
247}
248#[derive(Clone, Debug)]
250pub struct DiGraph {
251 pub n: usize,
253 pub adj: Vec<Vec<(usize, i64)>>,
255}
256impl DiGraph {
257 pub fn new(n: usize) -> Self {
259 Self {
260 n,
261 adj: vec![vec![]; n],
262 }
263 }
264 pub fn add_edge(&mut self, u: usize, v: usize, w: i64) {
266 self.adj[u].push((v, w));
267 }
268 pub fn bfs(&self, s: usize) -> Vec<usize> {
270 let mut dist = vec![usize::MAX; self.n];
271 let mut queue = VecDeque::new();
272 dist[s] = 0;
273 queue.push_back(s);
274 while let Some(u) = queue.pop_front() {
275 for &(v, _) in &self.adj[u] {
276 if dist[v] == usize::MAX {
277 dist[v] = dist[u] + 1;
278 queue.push_back(v);
279 }
280 }
281 }
282 dist
283 }
284 pub fn dfs(&self, s: usize) -> Vec<usize> {
286 let mut visited = vec![false; self.n];
287 let mut order = Vec::new();
288 self.dfs_visit(s, &mut visited, &mut order);
289 order
290 }
291 fn dfs_visit(&self, u: usize, visited: &mut Vec<bool>, order: &mut Vec<usize>) {
292 if visited[u] {
293 return;
294 }
295 visited[u] = true;
296 for &(v, _) in &self.adj[u] {
297 self.dfs_visit(v, visited, order);
298 }
299 order.push(u);
300 }
301 pub fn topo_sort(&self) -> Option<Vec<usize>> {
303 let mut in_degree = vec![0usize; self.n];
304 for u in 0..self.n {
305 for &(v, _) in &self.adj[u] {
306 in_degree[v] += 1;
307 }
308 }
309 let mut queue: VecDeque<usize> = (0..self.n).filter(|&u| in_degree[u] == 0).collect();
310 let mut order = Vec::new();
311 while let Some(u) = queue.pop_front() {
312 order.push(u);
313 for &(v, _) in &self.adj[u] {
314 in_degree[v] -= 1;
315 if in_degree[v] == 0 {
316 queue.push_back(v);
317 }
318 }
319 }
320 if order.len() == self.n {
321 Some(order)
322 } else {
323 None
324 }
325 }
326 pub fn scc(&self) -> Vec<Vec<usize>> {
328 let mut visited = vec![false; self.n];
329 let mut finish_order = Vec::new();
330 for u in 0..self.n {
331 if !visited[u] {
332 self.dfs_visit(u, &mut visited, &mut finish_order);
333 }
334 }
335 let mut transposed = DiGraph::new(self.n);
336 for u in 0..self.n {
337 for &(v, w) in &self.adj[u] {
338 transposed.add_edge(v, u, w);
339 }
340 }
341 let mut visited2 = vec![false; self.n];
342 let mut components = Vec::new();
343 for &u in finish_order.iter().rev() {
344 if !visited2[u] {
345 let mut comp = Vec::new();
346 transposed.dfs_visit(u, &mut visited2, &mut comp);
347 components.push(comp);
348 }
349 }
350 components
351 }
352 pub fn dijkstra(&self, s: usize) -> (Vec<i64>, Vec<Option<usize>>) {
355 use super::functions::*;
356 use std::cmp::Reverse;
357 let inf = i64::MAX / 2;
358 let mut dist = vec![inf; self.n];
359 let mut parent = vec![None; self.n];
360 dist[s] = 0;
361 let mut heap = BinaryHeap::new();
362 heap.push(Reverse((0i64, s)));
363 while let Some(Reverse((d, u))) = heap.pop() {
364 if d > dist[u] {
365 continue;
366 }
367 for &(v, w) in &self.adj[u] {
368 let nd = dist[u] + w;
369 if nd < dist[v] {
370 dist[v] = nd;
371 parent[v] = Some(u);
372 heap.push(Reverse((nd, v)));
373 }
374 }
375 }
376 (dist, parent)
377 }
378 pub fn bellman_ford(&self, s: usize) -> Option<Vec<i64>> {
381 let inf = i64::MAX / 2;
382 let mut dist = vec![inf; self.n];
383 dist[s] = 0;
384 for _ in 0..self.n - 1 {
385 let mut changed = false;
386 for u in 0..self.n {
387 if dist[u] == inf {
388 continue;
389 }
390 for &(v, w) in &self.adj[u] {
391 if dist[u] + w < dist[v] {
392 dist[v] = dist[u] + w;
393 changed = true;
394 }
395 }
396 }
397 if !changed {
398 break;
399 }
400 }
401 for u in 0..self.n {
402 if dist[u] == inf {
403 continue;
404 }
405 for &(v, w) in &self.adj[u] {
406 if dist[u] + w < dist[v] {
407 return None;
408 }
409 }
410 }
411 Some(dist)
412 }
413 pub fn floyd_warshall(&self) -> Vec<Vec<i64>> {
416 let inf = i64::MAX / 2;
417 let mut d = vec![vec![inf; self.n]; self.n];
418 for u in 0..self.n {
419 d[u][u] = 0;
420 for &(v, w) in &self.adj[u] {
421 d[u][v] = d[u][v].min(w);
422 }
423 }
424 for k in 0..self.n {
425 for i in 0..self.n {
426 for j in 0..self.n {
427 if d[i][k] < inf && d[k][j] < inf {
428 d[i][j] = d[i][j].min(d[i][k] + d[k][j]);
429 }
430 }
431 }
432 }
433 d
434 }
435 pub fn is_dag(&self) -> bool {
437 self.topo_sort().is_some()
438 }
439 pub fn reachable_count(&self, s: usize) -> usize {
441 let dist = self.bfs(s);
442 dist.iter().filter(|&&d| d != usize::MAX).count()
443 }
444}
445#[derive(Clone, Debug, Default)]
447pub struct UndirectedGraph {
448 pub n: usize,
450 pub adj: Vec<HashSet<usize>>,
452}
453impl UndirectedGraph {
454 pub fn new(n: usize) -> Self {
456 Self {
457 n,
458 adj: vec![HashSet::new(); n],
459 }
460 }
461 pub fn add_edge(&mut self, u: usize, v: usize) {
463 if u != v {
464 self.adj[u].insert(v);
465 self.adj[v].insert(u);
466 }
467 }
468 pub fn bfs(&self, s: usize) -> Vec<usize> {
470 let mut dist = vec![usize::MAX; self.n];
471 let mut queue = VecDeque::new();
472 dist[s] = 0;
473 queue.push_back(s);
474 while let Some(u) = queue.pop_front() {
475 for &v in &self.adj[u] {
476 if dist[v] == usize::MAX {
477 dist[v] = dist[u] + 1;
478 queue.push_back(v);
479 }
480 }
481 }
482 dist
483 }
484 pub fn is_connected(&self) -> bool {
486 if self.n == 0 {
487 return true;
488 }
489 let dist = self.bfs(0);
490 dist.iter().all(|&d| d != usize::MAX)
491 }
492 pub fn num_components(&self) -> usize {
494 let mut visited = vec![false; self.n];
495 let mut count = 0;
496 for u in 0..self.n {
497 if !visited[u] {
498 count += 1;
499 let mut stack = vec![u];
500 while let Some(v) = stack.pop() {
501 if visited[v] {
502 continue;
503 }
504 visited[v] = true;
505 for &w in &self.adj[v] {
506 if !visited[w] {
507 stack.push(w);
508 }
509 }
510 }
511 }
512 }
513 count
514 }
515 pub fn bipartite_coloring(&self) -> Option<Vec<usize>> {
517 let mut color = vec![usize::MAX; self.n];
518 for s in 0..self.n {
519 if color[s] != usize::MAX {
520 continue;
521 }
522 color[s] = 0;
523 let mut queue = VecDeque::new();
524 queue.push_back(s);
525 while let Some(u) = queue.pop_front() {
526 for &v in &self.adj[u] {
527 if color[v] == usize::MAX {
528 color[v] = 1 - color[u];
529 queue.push_back(v);
530 } else if color[v] == color[u] {
531 return None;
532 }
533 }
534 }
535 }
536 Some(color)
537 }
538 pub fn is_bipartite(&self) -> bool {
540 self.bipartite_coloring().is_some()
541 }
542 pub fn all_degrees_even(&self) -> bool {
544 (0..self.n).all(|u| self.adj[u].len() % 2 == 0)
545 }
546 pub fn has_eulerian_circuit(&self) -> bool {
548 self.is_connected() && self.all_degrees_even()
549 }
550 pub fn greedy_coloring(&self) -> (usize, Vec<usize>) {
552 let mut color = vec![usize::MAX; self.n];
553 let mut max_color = 0;
554 for u in 0..self.n {
555 let neighbor_colors: HashSet<usize> = self.adj[u]
556 .iter()
557 .filter(|&&v| color[v] != usize::MAX)
558 .map(|&v| color[v])
559 .collect();
560 let mut c = 0;
561 while neighbor_colors.contains(&c) {
562 c += 1;
563 }
564 color[u] = c;
565 max_color = max_color.max(c);
566 }
567 (max_color + 1, color)
568 }
569 pub fn is_proper_coloring(&self, coloring: &[usize]) -> bool {
571 for u in 0..self.n {
572 for &v in &self.adj[u] {
573 if coloring[u] == coloring[v] {
574 return false;
575 }
576 }
577 }
578 true
579 }
580 pub fn degree(&self, u: usize) -> usize {
582 self.adj[u].len()
583 }
584 pub fn edge_count(&self) -> usize {
586 (0..self.n).map(|u| self.adj[u].len()).sum::<usize>() / 2
587 }
588 pub fn spanning_tree(&self) -> Vec<(usize, usize)> {
591 if self.n == 0 {
592 return vec![];
593 }
594 let mut in_tree = vec![false; self.n];
595 let mut edges = Vec::new();
596 in_tree[0] = true;
597 for _ in 0..self.n - 1 {
598 let mut found = false;
599 for u in 0..self.n {
600 if !in_tree[u] {
601 continue;
602 }
603 for &v in &self.adj[u] {
604 if !in_tree[v] {
605 in_tree[v] = true;
606 edges.push((u, v));
607 found = true;
608 break;
609 }
610 }
611 if found {
612 break;
613 }
614 }
615 }
616 edges
617 }
618 pub fn complete(n: usize) -> Self {
620 let mut g = Self::new(n);
621 for u in 0..n {
622 for v in (u + 1)..n {
623 g.add_edge(u, v);
624 }
625 }
626 g
627 }
628 pub fn path(n: usize) -> Self {
630 let mut g = Self::new(n);
631 for i in 0..n.saturating_sub(1) {
632 g.add_edge(i, i + 1);
633 }
634 g
635 }
636 pub fn cycle(n: usize) -> Self {
638 let mut g = Self::path(n);
639 if n >= 3 {
640 g.add_edge(n - 1, 0);
641 }
642 g
643 }
644 pub fn complete_bipartite(m: usize, n: usize) -> Self {
646 let mut g = Self::new(m + n);
647 for u in 0..m {
648 for v in m..(m + n) {
649 g.add_edge(u, v);
650 }
651 }
652 g
653 }
654}
655#[allow(dead_code)]
660pub struct ExpanderChecker {
661 pub graph: UndirectedGraph,
663}
664#[allow(dead_code)]
665impl ExpanderChecker {
666 pub fn new(graph: UndirectedGraph) -> Self {
668 Self { graph }
669 }
670 pub fn edge_boundary(&self, subset: &[usize]) -> usize {
672 let in_set: HashSet<usize> = subset.iter().copied().collect();
673 let mut boundary = 0usize;
674 for &u in &in_set {
675 for &v in &self.graph.adj[u] {
676 if !in_set.contains(&v) {
677 boundary += 1;
678 }
679 }
680 }
681 boundary
682 }
683 pub fn approximate_cheeger(&self) -> f64 {
686 let n = self.graph.n;
687 if n == 0 {
688 return 0.0;
689 }
690 let half = n / 2;
691 let mut min_ratio = f64::INFINITY;
692 for u in 0..n {
693 let boundary = self.edge_boundary(&[u]);
694 let size = 1usize;
695 let ratio = boundary as f64 / size as f64;
696 if ratio < min_ratio {
697 min_ratio = ratio;
698 }
699 }
700 if half >= 2 {
701 for u in 0..n {
702 for v in (u + 1)..n {
703 if u == v {
704 continue;
705 }
706 let boundary = self.edge_boundary(&[u, v]);
707 let ratio = boundary as f64 / 2.0;
708 if ratio < min_ratio {
709 min_ratio = ratio;
710 }
711 }
712 }
713 }
714 if min_ratio.is_infinite() {
715 0.0
716 } else {
717 min_ratio
718 }
719 }
720 pub fn is_expander(&self, threshold: f64) -> bool {
722 self.approximate_cheeger() >= threshold
723 }
724}
725#[allow(dead_code)]
729pub struct GraphonSampler {
730 pub n: usize,
732 pub graphon: Box<dyn Fn(f64, f64) -> f64>,
734}
735#[allow(dead_code)]
736impl GraphonSampler {
737 pub fn new(n: usize, graphon: Box<dyn Fn(f64, f64) -> f64>) -> Self {
739 Self { n, graphon }
740 }
741 pub fn sample_deterministic(&self) -> UndirectedGraph {
744 let mut g = UndirectedGraph::new(self.n);
745 for i in 0..self.n {
746 let xi = (i as f64 + 0.5) / self.n as f64;
747 for j in (i + 1)..self.n {
748 let xj = (j as f64 + 0.5) / self.n as f64;
749 let w = (self.graphon)(xi, xj);
750 if w > 0.5 {
751 g.add_edge(i, j);
752 }
753 }
754 }
755 g
756 }
757 pub fn sample_at_threshold(&self, p: f64) -> UndirectedGraph {
759 let mut g = UndirectedGraph::new(self.n);
760 for i in 0..self.n {
761 let xi = (i as f64 + 0.5) / self.n as f64;
762 for j in (i + 1)..self.n {
763 let xj = (j as f64 + 0.5) / self.n as f64;
764 let w = (self.graphon)(xi, xj);
765 if w > p {
766 g.add_edge(i, j);
767 }
768 }
769 }
770 g
771 }
772}