graph/
lib.rs

1//! # Graph (DFS, BFS, Topological Sort, Kahn's)
2
3#![feature(let_chains)]
4
5/// 684m Redundant Connection
6struct Sol684;
7
8impl Sol684 {
9    pub fn find_redundant_connection(edges: Vec<Vec<i32>>) -> Vec<i32> {
10        println!("* {:?}", edges);
11
12        #[derive(Debug)]
13        struct DJSet {
14            parent: Vec<usize>,
15            rank: Vec<usize>,
16        }
17
18        impl DJSet {
19            fn new(count: usize) -> Self {
20                DJSet {
21                    parent: Vec::from_iter(0..=count),
22                    rank: vec![0; count + 1],
23                }
24            }
25
26            fn find(&mut self, v: usize) -> usize {
27                if v != self.parent[v] {
28                    self.parent[v] = self.find(self.parent[v]);
29                }
30                self.parent[v]
31            }
32
33            fn union(&mut self, u: usize, v: usize) -> bool {
34                let (u, v) = (self.find(u), self.find(v));
35                match u == v {
36                    true => false,
37                    false => {
38                        match self.rank[u] > self.rank[v] {
39                            true => self.parent[v] = u,
40                            _ => {
41                                self.parent[u] = v;
42                                if self.rank[v] == self.rank[u] {
43                                    self.rank[v] += 1;
44                                }
45                            }
46                        }
47                        true
48                    }
49                }
50            }
51        }
52
53        let mut djset = DJSet::new(edges.len());
54        for edge in edges {
55            println!("-> {:?} ~ {:?}", edge, djset);
56
57            if !djset.union(edge[0] as usize, edge[1] as usize) {
58                return vec![edge[0], edge[1]];
59            }
60        }
61
62        vec![]
63    }
64
65    fn find_redundant_connection_graph(edges: Vec<Vec<i32>>) -> Vec<i32> {
66        println!("* {:?}", edges);
67
68        let mut graph = vec![vec![]; edges.len() + 1];
69        for e in &edges {
70            graph[e[0] as usize].push(e[1] as usize);
71            graph[e[1] as usize].push(e[0] as usize);
72        }
73
74        println!("-> {:?}", graph);
75
76        let mut visited = vec![false; edges.len() + 1];
77        let mut prv = vec![0; edges.len() + 1];
78        let mut icycle = 0; // `None-Node` label for now
79
80        let mut q = vec![1];
81
82        while let Some(v) = q.pop() {
83            visited[v] = true;
84
85            graph[v].iter().for_each(|&u| {
86                match visited[u] {
87                    false => {
88                        prv[u] = v;
89                        q.push(u);
90                    }
91                    true => {
92                        if prv[v] != u && icycle == 0 {
93                            icycle = u; // `u` is starting a cycle
94                            prv[u] = v;
95                        }
96                    }
97                }
98            });
99        }
100
101        println!("-> {:?}", prv);
102
103        let mut cnodes = vec![false; edges.len() + 1];
104        while !cnodes[icycle] {
105            cnodes[icycle] = true;
106            icycle = prv[icycle];
107        }
108
109        println!("-> {:?}", cnodes);
110
111        edges
112            .iter()
113            .rev()
114            .skip_while(|&v| !cnodes[v[0] as usize] || !cnodes[v[1] as usize])
115            .take(1)
116            .fold(vec![], |_, v| v.clone())
117    }
118}
119
120/// 695m Max Area of Island
121struct Sol695;
122
123impl Sol695 {
124    pub fn max_area_of_island(grid: Vec<Vec<i32>>) -> i32 {
125        fn island(grid: &mut Vec<Vec<i32>>, r: usize, c: usize) -> i32 {
126            println!("-> @ {:?} ~ {}", (r, c), grid[r][c]);
127
128            match grid[r][c] {
129                0 => 0,
130                _ => {
131                    grid[r][c] = 0;
132
133                    let mut area = 1;
134                    if r > 0 {
135                        area += island(grid, r - 1, c);
136                    }
137                    if r + 1 < grid.len() {
138                        area += island(grid, r + 1, c);
139                    }
140                    if c > 0 {
141                        area += island(grid, r, c - 1);
142                    }
143                    if c + 1 < grid[r].len() {
144                        area += island(grid, r, c + 1);
145                    }
146                    area
147                }
148            }
149        }
150
151        let mut grid = grid;
152
153        let mut xarea = 0;
154        for r in 0..grid.len() {
155            for c in 0..grid[0].len() {
156                xarea = xarea.max(island(&mut grid, r, c));
157            }
158        }
159
160        println!(":: {}", xarea);
161
162        xarea
163    }
164}
165
166/// 753h Cracking the Safe
167struct Sol753 {}
168impl Sol753 {
169    pub fn crack_safe(n: i32, k: i32) -> String {
170        use std::collections::HashSet;
171
172        fn dfs(v: String, k: usize, euler_path: &mut Vec<char>, visited: &mut HashSet<String>) {
173            for chr in ('0'..='9').take(k) {
174                let mut u: String = v.chars().collect();
175                u.push(chr);
176
177                if !visited.contains(&u) {
178                    visited.insert(u.clone());
179                    dfs(u.chars().skip(1).collect(), k, euler_path, visited);
180
181                    euler_path.push(chr);
182                }
183            }
184        }
185
186        let mut visited: HashSet<String> = HashSet::new();
187        let mut euler_path: Vec<char> = vec![];
188
189        dfs(
190            vec!['0'; n as usize - 1].iter().collect(),
191            k as usize,
192            &mut euler_path,
193            &mut visited,
194        );
195
196        (0..n - 1).for_each(|_| euler_path.push('0'));
197
198        println!("-> {visited:?}");
199
200        euler_path.iter().collect()
201    }
202}
203
204/// 802m Find Eventual Safe States
205struct Sol802;
206
207impl Sol802 {
208    pub fn eventual_safe_nodes(graph: Vec<Vec<i32>>) -> Vec<i32> {
209        let n = graph.len();
210
211        let (mut rvs, mut ins) = (vec![vec![]; n], vec![0; n]);
212        (0..n).for_each(|v| {
213            graph[v].iter().for_each(|&u| {
214                ins[v] += 1;
215                rvs[u as usize].push(v);
216            });
217        });
218
219        println!(" -> {:?} -> {:?}", graph, rvs);
220        println!(" -> {:?}", ins);
221
222        let mut q: Vec<_> = ins
223            .iter()
224            .enumerate()
225            .filter_map(|(v, &degree)| if degree == 0 { Some(v) } else { None })
226            .collect();
227
228        let mut rst = vec![false; n];
229        while let Some(v) = q.pop() {
230            rst[v] = true;
231
232            for u in rvs[v].iter().cloned() {
233                ins[u] -= 1;
234                if ins[u] == 0 {
235                    q.push(u);
236                }
237            }
238        }
239
240        rst.iter()
241            .enumerate()
242            .filter_map(|(v, &flag)| if flag { Some(v as i32) } else { None })
243            .collect()
244    }
245}
246
247/// 827h Making A Large Island
248struct Sol827;
249
250impl Sol827 {
251    pub fn largest_island(grid: Vec<Vec<i32>>) -> i32 {
252        let mut grid = grid;
253        let (rows, cols) = (grid.len(), grid[0].len());
254        let dirs = [-1, 0, 1, 0, -1];
255
256        let mut areas = vec![0, 0];
257        let mut islands = 0;
258        for r in 0..rows {
259            for c in 0..cols {
260                if grid[r][c] == 1 {
261                    let mut area = 0;
262
263                    let mut q = Vec::from([(r, c)]);
264                    while let Some((r, c)) = q.pop() {
265                        if grid[r][c] != 1 {
266                            continue;
267                        }
268
269                        area += 1;
270                        grid[r][c] = 2 + islands;
271
272                        for i in 0..4 {
273                            let (r, c) = (
274                                r.wrapping_add_signed(dirs[i]),
275                                c.wrapping_add_signed(dirs[i + 1]),
276                            );
277                            if r < rows && c < cols {
278                                q.push((r, c));
279                            }
280                        }
281                    }
282
283                    areas.push(area);
284                    islands += 1;
285                }
286            }
287        }
288
289        println!("-> Grid: {grid:?}");
290        println!("-> Island Areas: {areas:?}");
291
292        use std::collections::HashSet;
293
294        let mut xarea = 0;
295        for r in 0..rows {
296            for c in 0..cols {
297                if grid[r][c] == 0 {
298                    let mut iset = HashSet::new();
299                    for i in 0..4 {
300                        let (r, c) = (
301                            r.wrapping_add_signed(dirs[i]),
302                            c.wrapping_add_signed(dirs[i + 1]),
303                        );
304                        if r < rows && c < cols {
305                            iset.insert(grid[r][c]);
306                        }
307                    }
308                    xarea = xarea.max(iset.iter().fold(0, |r, &v| r + areas[v as usize]) + 1);
309                }
310            }
311        }
312
313        match islands {
314            0 => 1,
315            1 if areas[2] as usize == rows * cols => areas[2],
316            _ => xarea,
317        }
318    }
319}
320
321/// 909m Snakes and Ladders
322struct Sol909 {}
323
324impl Sol909 {
325    /// 2 <= N <= 20
326    pub fn snakes_and_ladders(board: Vec<Vec<i32>>) -> i32 {
327        use std::collections::VecDeque;
328
329        let n = board.len();
330        let barray: Vec<i32> = board
331            .into_iter()
332            .rev()
333            .enumerate()
334            .flat_map(|(i, row)| {
335                if i & 1 == 0 {
336                    row
337                } else {
338                    row.into_iter().rev().collect()
339                }
340            })
341            .collect();
342
343        println!("-> Boustrophedon :: {barray:?}");
344
345        let mut dists = vec![i32::MAX; n * n];
346
347        let mut queue = VecDeque::from([0]);
348        dists[0] = 0;
349        while let Some(v) = queue.pop_front() {
350            println!("-> {v:>2} {queue:?}");
351
352            if v == n * n - 1 {
353                continue;
354            }
355
356            for (mut u, &jump) in barray
357                .iter()
358                .enumerate()
359                .take((v + 7).min(n * n))
360                .skip(v + 1)
361            {
362                if jump != -1 {
363                    u = jump as usize - 1;
364                }
365
366                if dists[u] > dists[v] + 1 {
367                    dists[u] = dists[v] + 1;
368                    queue.push_back(u);
369                }
370            }
371        }
372
373        println!("-> Distances :: {dists:?}");
374
375        if dists[n * n - 1] == i32::MAX {
376            return -1;
377        }
378        dists[n * n - 1]
379    }
380}
381
382/// 1267m Count Servers that Communicate
383struct Sol1267;
384
385impl Sol1267 {
386    pub fn count_servers(grid: Vec<Vec<i32>>) -> i32 {
387        let (rows, cols) = (grid.len(), grid[0].len());
388
389        let rn: Vec<_> = (0..rows)
390            .map(|r| (0..cols).filter(|&c| grid[r][c] == 1).count())
391            .collect();
392        let cn: Vec<_> = (0..cols)
393            .map(|c| (0..rows).filter(|&r| grid[r][c] == 1).count())
394            .collect();
395
396        println!(" -> R: {:?}   C: {:?}", rn, cn);
397
398        (0..rows)
399            .flat_map(|r| (0..cols).map(move |c| (r, c)))
400            .filter(|&(r, c)| rn[r] > 1 || cn[c] > 1)
401            .map(|(r, c)| grid[r][c])
402            .sum()
403    }
404}
405
406/// 1298h Maximum Candies You Can Get from Boxes
407struct Sol1298 {}
408
409impl Sol1298 {
410    pub fn max_candies(
411        status: Vec<i32>,
412        candies: Vec<i32>,
413        keys: Vec<Vec<i32>>,
414        contained_boxes: Vec<Vec<i32>>,
415        initial_boxes: Vec<i32>,
416    ) -> i32 {
417        let mut gots = vec![false; status.len()];
418        let mut opened = vec![false; status.len()];
419        let mut can_open: Vec<_> = status.iter().map(|&v| v == 1).collect();
420
421        use std::collections::VecDeque;
422
423        let mut queue = VecDeque::new();
424        for ibox in initial_boxes.iter().map(|&v| v as usize) {
425            gots[ibox] = true;
426            if can_open[ibox] {
427                queue.push_back(ibox);
428                opened[ibox] = true;
429            }
430        }
431
432        let mut total = 0;
433        while let Some(qbox) = queue.pop_front() {
434            total += candies[qbox];
435
436            for kbox in keys[qbox].iter().map(|&v| v as usize) {
437                can_open[kbox] = true;
438                if gots[kbox] && !opened[kbox] {
439                    queue.push_back(kbox);
440                    opened[kbox] = true;
441                }
442            }
443
444            for gbox in contained_boxes[qbox].iter().map(|&v| v as usize) {
445                gots[gbox] = true;
446                if can_open[gbox] && !opened[gbox] {
447                    queue.push_back(gbox);
448                    opened[gbox] = true;
449                }
450            }
451        }
452
453        total
454    }
455}
456
457/// 1368h Minimum Cost to Make at Least One Valid Path in a Grid
458struct Sol1368;
459
460impl Sol1368 {
461    pub fn min_cost(grid: Vec<Vec<i32>>) -> i32 {
462        use std::cmp::Reverse;
463        use std::collections::BinaryHeap;
464
465        let (rows, cols) = (grid.len(), grid[0].len());
466        let mut costs = vec![vec![i32::MAX; cols]; rows];
467
468        let mut pq = BinaryHeap::new();
469        pq.push(Reverse((0, 0i32, 0i32)));
470        costs[0][0] = 0;
471
472        println!(" -> {:?}", pq);
473        while let Some(Reverse((w, r, c))) = pq.pop() {
474            if costs[r as usize][c as usize] < w {
475                continue;
476            }
477
478            print!(" -> {:?} :: ", (w, r, c));
479
480            [(0, 1), (0, -1), (1, 0), (-1, 0)]
481                .into_iter()
482                .zip(1..=4)
483                .inspect(|o| print!(" {:?}", o))
484                .for_each(|((dx, dy), dir)| {
485                    let w = w + (dir != grid[r as usize][c as usize]) as i32;
486                    let (r, c) = (r + dx, c + dy);
487                    if 0 <= r
488                        && r < rows as i32
489                        && 0 <= c
490                        && c < cols as i32
491                        && w < costs[r as usize][c as usize]
492                    {
493                        costs[r as usize][c as usize] = w;
494                        pq.push(Reverse((w, r, c)));
495                    }
496                });
497
498            println!();
499            println!(" -> {:?}", pq);
500        }
501
502        println!(" :: {}", costs[rows - 1][cols - 1]);
503
504        costs[rows - 1][cols - 1]
505    }
506
507    fn min_cost_bfs01(grid: Vec<Vec<i32>>) -> i32 {
508        use std::collections::VecDeque;
509
510        let (rows, cols) = (grid.len(), grid[0].len());
511        let mut costs = vec![vec![i32::MAX; cols]; rows];
512
513        let mut q = VecDeque::new();
514
515        q.push_front((0i32, 0i32));
516        costs[0][0] = 0;
517
518        println!(" -> {:?}", q);
519
520        while let Some((r, c)) = q.pop_front() {
521            let curw = costs[r as usize][c as usize];
522
523            [(0, 1), (0, -1), (1, 0), (-1, 0)]
524                .into_iter()
525                .zip(1..=4)
526                .for_each(|((dx, dy), dir)| {
527                    let w = (grid[r as usize][c as usize] != dir) as i32;
528                    let (r, c) = (r + dx, c + dy);
529                    if 0 <= r
530                        && r < rows as i32
531                        && 0 <= c
532                        && c < cols as i32
533                        && curw + w < costs[r as usize][c as usize]
534                    {
535                        costs[r as usize][c as usize] = curw + w;
536                        match w {
537                            0 => q.push_front((r, c)),
538                            _ => q.push_back((r, c)),
539                        }
540                    }
541                });
542
543            println!(" -> {:?}", q);
544        }
545
546        println!(" :: {}", costs[rows - 1][cols - 1]);
547
548        costs[rows - 1][cols - 1]
549    }
550}
551
552/// 1462m Course Schedule IV
553struct Sol1462;
554
555impl Sol1462 {
556    pub fn check_if_prerequisite(
557        num_courses: i32,
558        prerequisites: Vec<Vec<i32>>,
559        queries: Vec<Vec<i32>>,
560    ) -> Vec<bool> {
561        let mut graph = vec![vec![]; num_courses as usize];
562
563        prerequisites.iter().for_each(|v| {
564            graph[v[0] as usize].push(v[1] as usize);
565        });
566
567        println!(" -> {:?}", graph);
568
569        let mut floyd_warshall = vec![vec![false; num_courses as usize]; num_courses as usize];
570        prerequisites.iter().for_each(|v| {
571            floyd_warshall[v[0] as usize][v[1] as usize] = true;
572        });
573        (0..num_courses as usize).for_each(|v| floyd_warshall[v][v] = true);
574
575        (0..num_courses as usize).for_each(|src| {
576            (0..num_courses as usize).for_each(|dst| {
577                (0..num_courses as usize).for_each(|via| {
578                    floyd_warshall[src][dst] |=
579                        floyd_warshall[src][via] && floyd_warshall[via][dst];
580                })
581            })
582        });
583
584        println!(" -> {:?}", floyd_warshall);
585
586        let mut memory = vec![vec![false; num_courses as usize]; num_courses as usize];
587
588        (0..num_courses as usize).for_each(|src| {
589            let mut q = vec![];
590            q.push(src);
591
592            while let Some(v) = q.pop() {
593                memory[src][v] = true;
594                graph[v].iter().for_each(|&u| {
595                    if !memory[src][u] {
596                        q.push(u)
597                    }
598                });
599            }
600        });
601
602        assert_eq!(memory, floyd_warshall);
603
604        queries.into_iter().fold(vec![], |mut rst, qry| {
605            rst.push(memory[qry[0] as usize][qry[1] as usize]);
606            rst
607        })
608    }
609}
610
611/// 1765m Map of Highest Peak
612struct Sol1765;
613
614impl Sol1765 {
615    pub fn highest_peak(is_water: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
616        use std::collections::VecDeque;
617
618        let (rows, cols) = (is_water.len(), is_water[0].len());
619        let mut q = VecDeque::new();
620        let mut visited = vec![vec![false; cols]; rows];
621
622        (0..rows).for_each(|r| {
623            (0..cols).for_each(|c| {
624                if is_water[r][c] == 1 {
625                    q.push_back((r as i32, c as i32, 0));
626                    visited[r][c] = true;
627                }
628            })
629        });
630
631        let mut rst = vec![vec![0; cols]; rows];
632        let dirs = [-1, 0, 1, 0, -1];
633
634        println!(" -> {:?}", q);
635        while let Some((r, c, h)) = q.pop_front() {
636            println!(" -> {:?}", q);
637
638            (0..4).for_each(|i| {
639                let (x, y) = (r + dirs[i], c + dirs[i + 1]);
640                if 0 <= x
641                    && x < rows as i32
642                    && 0 <= y
643                    && y < cols as i32
644                    && !visited[x as usize][y as usize]
645                {
646                    visited[x as usize][y as usize] = true;
647                    rst[x as usize][y as usize] = h + 1;
648                    q.push_back((x, y, h + 1));
649                }
650            });
651        }
652
653        rst
654    }
655}
656
657/// 1976m Number of Ways to Arrive at Destination
658struct Sol1976;
659
660impl Sol1976 {
661    /// 1 <= n <= 200
662    /// 0 <= u, v <= n-1
663    /// 1 <= t <= 10^9
664    pub fn count_paths(n: i32, roads: Vec<Vec<i32>>) -> i32 {
665        let n = n as usize;
666        const M: u64 = 1e9 as u64 + 7;
667
668        // [][](Time, #Path)
669        let mut graph = vec![vec![(1e9 as u64 * 200 + 1, 0); n]; n];
670        for road in roads {
671            let (u, v, t) = (road[0] as usize, road[1] as usize, road[2] as u64);
672            graph[u][v] = (t, 1);
673            graph[v][u] = (t, 1);
674        }
675
676        for (i, vc) in graph.iter_mut().enumerate() {
677            vc[i] = (0u64, 1);
678        }
679
680        use std::cmp::Ordering::*;
681
682        // Floyd-Warshall O(N^3)
683        for m in 0..n {
684            for v in 0..n {
685                for u in 0..n {
686                    if v != m && u != m {
687                        match (graph[u][m].0 + graph[m][v].0).cmp(&graph[u][v].0) {
688                            Less => {
689                                graph[u][v].0 = graph[u][m].0 + graph[m][v].0;
690                                graph[u][v].1 = (graph[u][m].1 * graph[m][v].1) % M;
691                            }
692                            Equal => {
693                                graph[u][v].1 += (graph[u][m].1 * graph[m][v].1) % M;
694                                graph[u][v].1 %= M;
695                            }
696                            _ => {}
697                        }
698                    }
699                }
700            }
701        }
702
703        println!("-> {:?}", graph);
704
705        graph[0][n - 1].1 as i32
706    }
707}
708
709/// 2127h Maximum Employees to Be Invited to a Meeting
710struct Sol2127;
711
712impl Sol2127 {
713    pub fn maximum_invitations(favorite: Vec<i32>) -> i32 {
714        use std::collections::VecDeque;
715
716        let n = favorite.len();
717        let mut ins = vec![0; n];
718        favorite.iter().for_each(|&f| ins[f as usize] += 1);
719
720        let mut q = VecDeque::from(
721            ins.iter()
722                .enumerate()
723                .filter_map(|(v, &degree)| if degree == 0 { Some(v) } else { None })
724                .collect::<Vec<_>>(),
725        );
726
727        let mut depth = vec![1; n];
728
729        while let Some(v) = q.pop_front() {
730            let u = favorite[v] as usize;
731
732            depth[u] = depth[u].max(depth[v] + 1);
733            ins[u] -= 1;
734            if ins[u] == 0 {
735                q.push_back(u);
736            }
737        }
738
739        let (mut lcycle, mut tcycle) = (0, 0);
740        (0..n).for_each(|v| {
741            if ins[v] != 0 {
742                let (mut l, mut cur) = (0, v);
743                while ins[cur] > 0 {
744                    ins[cur] = 0;
745                    l += 1;
746                    cur = favorite[cur] as usize;
747                }
748
749                match l {
750                    2 => tcycle += depth[v] + depth[favorite[v] as usize],
751                    _ => lcycle = lcycle.max(l),
752                }
753            }
754        });
755
756        println!(" :: {:?}", (lcycle, tcycle));
757
758        lcycle.max(tcycle)
759    }
760}
761
762/// 2359m Find Closed Node to Given Two Nodes
763struct Sol2359 {}
764
765impl Sol2359 {
766    /// 2 <= N <= 10^5
767    pub fn closest_meeting_node(edges: Vec<i32>, node1: i32, node2: i32) -> i32 {
768        fn dfs(v: usize, dists: &mut [i32], edges: &[i32]) {
769            let u = edges[v];
770            if u != -1 && dists[u as usize] == i32::MAX {
771                dists[u as usize] = dists[v] + 1;
772                dfs(u as usize, dists, edges);
773            }
774        }
775
776        fn bfs(src: usize, dists: &mut [i32], edges: &[i32]) {
777            use std::collections::VecDeque;
778
779            let mut queue = VecDeque::from([src]);
780            dists[src] = 0;
781
782            while let Some(v) = queue.pop_front() {
783                let u = edges[v];
784                if u != -1 && dists[u as usize] == i32::MAX {
785                    dists[u as usize] = dists[v] + 1;
786                    queue.push_back(u as usize);
787                }
788            }
789        }
790
791        let (mut dists1, mut dists2) = (vec![i32::MAX; edges.len()], vec![i32::MAX; edges.len()]);
792        (dists1[node1 as usize], dists2[node2 as usize]) = (0, 0);
793
794        dfs(node1 as usize, &mut dists1, &edges);
795        println!("-> {node1} ~ {dists1:?}");
796
797        bfs(node2 as usize, &mut dists2, &edges);
798        println!("-> {node2} ~ {dists2:?}");
799
800        (0..edges.len())
801            .fold((-1, i32::MAX), |(m_node, m_dist), v| {
802                if m_dist > dists1[v].max(dists2[v]) {
803                    (v as i32, dists1[v].max(dists2[v]))
804                } else {
805                    (m_node, m_dist)
806                }
807            })
808            .0
809    }
810}
811
812/// 2467m Most Profitable Path in a Tree
813struct Sol2467;
814
815impl Sol2467 {
816    pub fn most_profitable_path(edges: Vec<Vec<i32>>, bob: i32, amount: Vec<i32>) -> i32 {
817        let n = edges.len() + 1;
818        let mut graph = vec![vec![]; n];
819
820        for e in edges {
821            graph[e[0] as usize].push(e[1] as usize);
822            graph[e[1] as usize].push(e[0] as usize);
823        }
824
825        println!("-> {:?}", graph);
826
827        let mut bdist = vec![100_000; n];
828        bdist[bob as usize] = 0;
829
830        fn search(
831            u: usize,
832            p: usize,
833            time: usize,
834            graph: &Vec<Vec<usize>>,
835            bdist: &mut Vec<usize>,
836            amount: &Vec<i32>,
837        ) -> i32 {
838            let mut profit = 0;
839            let mut neighbors = i32::MIN;
840
841            for &v in &graph[u] {
842                if v != p {
843                    neighbors = neighbors.max(search(v, u, time + 1, graph, bdist, amount));
844                    bdist[u] = bdist[u].min(bdist[v] + 1);
845                }
846            }
847
848            use std::cmp::Ordering::*;
849            profit += match bdist[u].cmp(&time) {
850                Greater => amount[u],
851                Equal => amount[u] / 2,
852                _ => 0,
853            };
854
855            match neighbors {
856                i32::MIN => profit,
857                _ => profit + neighbors,
858            }
859        }
860
861        search(0, n, 0, &graph, &mut bdist, &amount)
862    }
863}
864
865/// 2493h Divide Nodes Into the Maximum Number of Groups
866struct Sol2493;
867
868impl Sol2493 {
869    pub fn magnificent_sets(n: i32, edges: Vec<Vec<i32>>) -> i32 {
870        use std::collections::VecDeque;
871
872        println!("* {:?}", edges);
873
874        let mut graph = vec![vec![]; n as usize + 1];
875        for e in &edges {
876            graph[e[0] as usize].push(e[1] as usize);
877            graph[e[1] as usize].push(e[0] as usize);
878        }
879        println!("-> graph :: {:?}", graph);
880
881        let mut bicolors = vec![-1; graph.len()];
882        for v in 1..graph.len() {
883            if bicolors[v] != -1 {
884                continue;
885            }
886
887            bicolors[v] = 0;
888            let mut q = vec![v];
889
890            while let Some(v) = q.pop() {
891                println!("-> {} {:?}", v, q);
892
893                for &u in &graph[v] {
894                    if bicolors[u] == bicolors[v] {
895                        return -1; // graph is not `BiPartite`
896                    }
897                    if bicolors[u] != -1 {
898                        continue;
899                    }
900
901                    bicolors[u] = bicolors[v] ^ 1;
902                    q.push(u);
903                }
904            }
905        }
906        println!("-> colors :: {:?}", bicolors);
907
908        let mut dist = vec![0; graph.len()];
909        for n in 1..graph.len() {
910            let mut dq = VecDeque::new();
911            let mut visited = vec![false; graph.len()];
912
913            dq.push_back(n);
914            visited[n] = true;
915
916            let mut xdist = 0;
917            while !dq.is_empty() {
918                for _ in 0..dq.len() {
919                    if let Some(v) = dq.pop_front() {
920                        for &u in &graph[v] {
921                            if !visited[u] {
922                                visited[u] = true;
923                                dq.push_back(u);
924                            }
925                        }
926                    }
927                }
928                xdist += 1;
929            }
930
931            dist[n] = xdist;
932        }
933        println!("-> distances :: {:?}", dist);
934
935        let mut groups = 0;
936        let mut visited = vec![false; graph.len()];
937        for n in 1..graph.len() {
938            if !visited[n] {
939                let mut ngroup = 0;
940                let mut q = vec![n];
941                visited[n] = true;
942                while let Some(v) = q.pop() {
943                    ngroup = ngroup.max(dist[v]);
944                    for &u in &graph[v] {
945                        if !visited[u] {
946                            visited[u] = true;
947                            q.push(u);
948                        }
949                    }
950                }
951
952                groups += ngroup;
953            }
954        }
955
956        groups
957    }
958}
959
960/// 2503h Maximum Number of Points From Grid Queries
961struct Sol2503;
962
963impl Sol2503 {
964    pub fn max_points(grid: Vec<Vec<i32>>, queries: Vec<i32>) -> Vec<i32> {
965        use std::cmp::Reverse;
966        use std::collections::BinaryHeap;
967
968        let mut sqry = vec![];
969        for (i, &qry) in queries.iter().enumerate() {
970            sqry.push((qry, i));
971        }
972        sqry.sort_unstable();
973        println!("-> {:?}", sqry);
974
975        let (rows, cols) = (grid.len(), grid[0].len());
976        let mut visited = vec![vec![false; cols]; rows];
977
978        let mut pq = BinaryHeap::new();
979
980        pq.push(Reverse((grid[0][0], 0usize, 0usize)));
981        visited[0][0] = true;
982
983        let mut rst = vec![0; queries.len()];
984        let mut points = 0;
985
986        const DIRS: [isize; 5] = [-1, 0, 1, 0, -1];
987        for (qry, i) in sqry {
988            while let Some(&Reverse((gval, r, c))) = pq.peek()
989                && gval < qry
990            {
991                println!("-> {} {:?}", gval, (r, c));
992
993                pq.pop();
994                points += 1;
995
996                for d in 0..4 {
997                    let (r, c) = (
998                        r.overflowing_add_signed(DIRS[d]).0,
999                        c.overflowing_add_signed(DIRS[d + 1]).0,
1000                    );
1001
1002                    if r < rows && c < cols && !visited[r][c] {
1003                        visited[r][c] = true;
1004                        pq.push(Reverse((grid[r][c], r, c)));
1005
1006                        println!("-> * {:?} {:?}", (r, c), &pq);
1007                    }
1008                }
1009            }
1010
1011            rst[i] = points;
1012        }
1013
1014        rst
1015    }
1016}
1017
1018/// 2608h Shortest Cycle in a Graph
1019struct Sol2608;
1020
1021impl Sol2608 {
1022    pub fn find_shortest_cycle(n: i32, edges: Vec<Vec<i32>>) -> i32 {
1023        use std::collections::VecDeque;
1024
1025        println!("* {:?}", edges);
1026
1027        let n = n as usize;
1028        let mut graph = vec![vec![]; n];
1029        for e in &edges {
1030            let (v, u) = (e[0] as usize, e[1] as usize);
1031            graph[v].push(u);
1032            graph[u].push(v);
1033        }
1034        println!("-> graph :: {:?}", graph);
1035
1036        let mut mcycle = usize::MAX;
1037        (0..n).for_each(|src| {
1038            let mut dist = vec![usize::MAX; n];
1039
1040            let mut dq = VecDeque::new();
1041            dq.push_back(src);
1042            dist[src] = 0;
1043
1044            while let Some(v) = dq.pop_front() {
1045                println!(" -> {} {:?}", v, dq);
1046
1047                for &u in &graph[v] {
1048                    match dist[u] {
1049                        usize::MAX => {
1050                            dist[u] = dist[v] + 1;
1051                            dq.push_back(u);
1052                        }
1053                        _ => {
1054                            if dist[v] <= dist[u] {
1055                                mcycle = mcycle.min(dist[u] + dist[v] + 1);
1056                            }
1057                        }
1058                    }
1059                }
1060            }
1061        });
1062
1063        match mcycle {
1064            usize::MAX => -1,
1065            _ => mcycle as i32,
1066        }
1067    }
1068}
1069
1070/// 2658m Maximum Number of Fish in a Grid
1071struct Sol2658;
1072
1073impl Sol2658 {
1074    pub fn find_max_fish(grid: Vec<Vec<i32>>) -> i32 {
1075        println!("* {:?}", grid);
1076
1077        let (rows, cols) = (grid.len(), grid[0].len());
1078        let mut visited = vec![vec![false; cols]; rows];
1079
1080        let dir = [-1, 0, 1, 0, -1];
1081        let mut xfish = 0;
1082
1083        (0..rows).for_each(|r| {
1084            (0..cols).for_each(|c| {
1085                if grid[r][c] != 0 && !visited[r][c] {
1086                    println!("-> {:?}", (r, c));
1087
1088                    let mut fish = 0;
1089                    let mut q = vec![];
1090
1091                    q.push((r as i32, c as i32));
1092                    visited[r][c] = true;
1093
1094                    while let Some((r, c)) = q.pop() {
1095                        println!(" -> {:?}", (r, c));
1096
1097                        fish += grid[r as usize][c as usize];
1098                        xfish = xfish.max(fish);
1099
1100                        (0..4).for_each(|i| {
1101                            let (r, c) = (r + dir[i], c + dir[i + 1]);
1102                            if 0 <= r
1103                                && r < rows as i32
1104                                && 0 <= c
1105                                && c < cols as i32
1106                                && grid[r as usize][c as usize] != 0
1107                                && !visited[r as usize][c as usize]
1108                            {
1109                                visited[r as usize][c as usize] = true;
1110                                q.push((r, c));
1111                            }
1112                        })
1113                    }
1114                }
1115            })
1116        });
1117
1118        xfish
1119    }
1120
1121    fn find_max_fish_recursion(grid: Vec<Vec<i32>>) -> i32 {
1122        fn dfs(grid: &mut Vec<Vec<i32>>, r: usize, c: usize) -> i32 {
1123            if grid[r][c] == 0 {
1124                return 0;
1125            }
1126
1127            let mut fish = grid[r][c];
1128            grid[r][c] = 0;
1129
1130            if r > 0 {
1131                fish += dfs(grid, r - 1, c);
1132            }
1133            if r + 1 < grid.len() {
1134                fish += dfs(grid, r + 1, c);
1135            }
1136            if c > 0 {
1137                fish += dfs(grid, r, c - 1);
1138            }
1139            if c + 1 < grid[0].len() {
1140                fish += dfs(grid, r, c + 1);
1141            }
1142
1143            fish
1144        }
1145
1146        let mut grid = grid;
1147        let mut xfish = 0;
1148
1149        (0..grid.len())
1150            .for_each(|r| (0..grid[0].len()).for_each(|c| xfish = xfish.max(dfs(&mut grid, r, c))));
1151
1152        xfish
1153    }
1154}
1155
1156/// 2685m Count the Number of Complete Components
1157struct Sol2685;
1158
1159impl Sol2685 {
1160    pub fn count_complete_components(n: i32, edges: Vec<Vec<i32>>) -> i32 {
1161        let mut cliques = 0;
1162
1163        let n = n as usize;
1164        let mut graph = vec![vec![]; n];
1165
1166        for edge in edges {
1167            let (v, u) = (edge[0] as usize, edge[1] as usize);
1168            graph[v].push(u);
1169            graph[u].push(v);
1170        }
1171
1172        println!("-> {:?}", graph);
1173
1174        fn dfs(graph: &[Vec<usize>], visited: &mut [bool], v: usize) -> (usize, usize) {
1175            let (mut vertices, mut edges) = (1, 0);
1176
1177            for &u in &graph[v] {
1178                edges += 1;
1179                if !visited[u] {
1180                    visited[u] = true;
1181
1182                    let rst = dfs(graph, visited, u);
1183                    vertices += rst.0;
1184                    edges += rst.1;
1185                }
1186            }
1187
1188            (vertices, edges)
1189        }
1190
1191        let mut visited = vec![false; n];
1192        for v in 0..n {
1193            if visited[v] {
1194                continue;
1195            }
1196            visited[v] = true;
1197
1198            let (vertices, edges) = dfs(&graph, &mut visited, v);
1199            if vertices * (vertices - 1) == edges {
1200                cliques += 1;
1201            }
1202        }
1203
1204        cliques
1205    }
1206}
1207
1208/// 3108h Minimum Cost Walk in Weighted Graph
1209struct Sol3108;
1210
1211impl Sol3108 {
1212    pub fn minimum_cost(n: i32, edges: Vec<Vec<i32>>, query: Vec<Vec<i32>>) -> Vec<i32> {
1213        use std::cmp::Ordering::*;
1214
1215        let n = n as usize;
1216        let mut djset: Vec<usize> = (0..n).collect();
1217        let mut ranks = vec![0; n];
1218        let mut weights = vec![usize::MAX; n];
1219
1220        fn find(djset: &mut [usize], x: usize) -> usize {
1221            if djset[x] != x {
1222                djset[x] = find(djset, djset[x]);
1223            }
1224            djset[x]
1225        }
1226
1227        fn union(djset: &mut [usize], ranks: &mut [usize], x: usize, y: usize) -> usize {
1228            let x = find(djset, x);
1229            let y = find(djset, y);
1230            match x.cmp(&y) {
1231                Equal => x,
1232                _ => match ranks[x].cmp(&ranks[y]) {
1233                    Less => {
1234                        djset[x] = y;
1235                        y
1236                    }
1237                    _ => {
1238                        djset[y] = x;
1239                        if ranks[x] == ranks[y] {
1240                            ranks[x] += 1;
1241                        }
1242                        x
1243                    }
1244                },
1245            }
1246        }
1247
1248        for v in &edges {
1249            union(&mut djset, &mut ranks, v[0] as usize, v[1] as usize);
1250        }
1251
1252        for v in &edges {
1253            let r = find(&mut djset, v[0] as usize);
1254            weights[r] &= v[2] as usize;
1255        }
1256
1257        println!("-> {:?}", (&djset, &ranks, &weights));
1258
1259        let mut rst = vec![];
1260        for v in query {
1261            let (x, y) = (
1262                find(&mut djset, v[0] as usize),
1263                find(&mut djset, v[1] as usize),
1264            );
1265            match x.cmp(&y) {
1266                Equal => rst.push(weights[x] as i32),
1267                _ => rst.push(-1),
1268            }
1269        }
1270
1271        rst
1272    }
1273}
1274
1275/// 3341m Find Minimum Time to Reach Last Room I
1276struct Sol3341;
1277
1278impl Sol3341 {
1279    pub fn min_time_to_reach(move_time: Vec<Vec<i32>>) -> i32 {
1280        use std::cmp::Reverse;
1281        use std::collections::BinaryHeap;
1282
1283        let (rows, cols) = (move_time.len(), move_time[0].len());
1284        let mut grid = vec![vec![i32::MAX; cols]; rows];
1285        let mut pq = BinaryHeap::new();
1286
1287        grid[0][0] = 0;
1288        pq.push(Reverse((0, 0, 0)));
1289
1290        while let Some(Reverse((time, r, c))) = pq.pop() {
1291            println!("-> {:?}", (time, r, c, &pq, &grid));
1292
1293            if r == rows - 1 && c == cols - 1 {
1294                return time;
1295            }
1296
1297            let dirs = [-1, 0, 1, 0, -1];
1298            for d in 0..4 {
1299                if let (Some(r), Some(c)) = (
1300                    r.checked_add_signed(dirs[d]),
1301                    c.checked_add_signed(dirs[d + 1]),
1302                ) {
1303                    if r < rows && c < cols && move_time[r][c].max(time) + 1 < grid[r][c] {
1304                        grid[r][c] = move_time[r][c].max(time) + 1;
1305                        pq.push(Reverse((grid[r][c], r, c)));
1306                    }
1307                }
1308            }
1309        }
1310
1311        -1
1312    }
1313}
1314
1315/// 3342m Find Minimum Time to Reach Last Room II
1316struct Sol3342;
1317
1318impl Sol3342 {
1319    pub fn min_time_to_reach(move_time: Vec<Vec<i32>>) -> i32 {
1320        use std::cmp::Reverse;
1321
1322        let (rows, cols) = (move_time.len(), move_time[0].len());
1323        let mut grid = vec![vec![i32::MAX; cols]; rows]; // Distances from {0,0}
1324
1325        let dirs = [-1, 0, 1, 0, -1];
1326        let mut pq = std::collections::BinaryHeap::new();
1327
1328        pq.push(Reverse((0, 0, 0, false)));
1329        grid[0][0] = 0;
1330
1331        while let Some(Reverse((time, r, c, double))) = pq.pop() {
1332            println!("-> {:?}", (time, r, c, double, &pq, &grid));
1333
1334            if r + 1 == rows && c + 1 == cols {
1335                return time;
1336            }
1337
1338            let delta = if double { 2 } else { 1 };
1339
1340            for d in 0..4 {
1341                if let (Some(r), Some(c)) = (
1342                    r.checked_add_signed(dirs[d]),
1343                    c.checked_add_signed(dirs[d + 1]),
1344                ) {
1345                    if r < rows && c < cols && move_time[r][c].max(time) + delta < grid[r][c] {
1346                        grid[r][c] = move_time[r][c].max(time) + delta;
1347                        pq.push(Reverse((grid[r][c], r, c, !double)));
1348                    }
1349                }
1350            }
1351        }
1352
1353        -1
1354    }
1355}
1356
1357/// 3372m Maximize the Number of Target Nodes After Connecting Trees I
1358struct Sol3372 {}
1359
1360impl Sol3372 {
1361    /// 2 <= M, N <= 1000
1362    /// 0 <= K <= 1000
1363    pub fn max_target_nodes(edges1: Vec<Vec<i32>>, edges2: Vec<Vec<i32>>, k: i32) -> Vec<i32> {
1364        let (mut tree1, mut tree2) = (
1365            vec![vec![]; edges1.len() + 1],
1366            vec![vec![]; edges2.len() + 1],
1367        );
1368
1369        let mk_adjs = |tree: &mut [Vec<usize>], edges: &[Vec<i32>]| {
1370            for edge in edges {
1371                tree[edge[0] as usize].push(edge[1] as usize);
1372                tree[edge[1] as usize].push(edge[0] as usize);
1373            }
1374        };
1375
1376        for (tree, edges) in [(&mut tree1, &edges1), (&mut tree2, &edges2)] {
1377            mk_adjs(tree, edges);
1378            println!("-> {edges:?} => {tree:?}");
1379        }
1380
1381        fn dfs(v: usize, p: usize, k: i32, tree: &[Vec<usize>], dists: &mut [i32]) {
1382            for &u in &tree[v] {
1383                if u != p {
1384                    dists[u] = dists[v] + 1;
1385                    if dists[u] < k {
1386                        dfs(u, v, k, tree, dists);
1387                    }
1388                }
1389            }
1390        }
1391
1392        let mut trgs = vec![];
1393        for src in 0..=edges2.len() {
1394            let mut dists = vec![i32::MAX; edges2.len() + 1];
1395            dists[src] = 0;
1396            dfs(src, usize::MAX, k - 1, &tree2, &mut dists);
1397            println!("-> {src} {dists:?}");
1398
1399            trgs.push(dists.iter().filter(|&&d| d <= k - 1).count());
1400        }
1401        println!("-> {trgs:?}");
1402
1403        let mut xtrgs = vec![];
1404        if let Some(&xtrg) = trgs.iter().max() {
1405            for src in 0..=edges1.len() {
1406                let mut dists = vec![i32::MAX; edges1.len() + 1];
1407                dists[src] = 0;
1408                dfs(src, usize::MAX, k, &tree1, &mut dists);
1409                println!("-> {src} {dists:?}");
1410
1411                xtrgs.push((dists.iter().filter(|&&d| d <= k).count() + xtrg) as i32);
1412            }
1413        }
1414
1415        xtrgs
1416    }
1417}
1418
1419/// 3373m Maximize the Number of Target Nodes After Connecting Trees II
1420struct Sol3373 {}
1421
1422impl Sol3373 {
1423    pub fn max_target_nodes(edges1: Vec<Vec<i32>>, edges2: Vec<Vec<i32>>) -> Vec<i32> {
1424        let (mut tree1, mut tree2) = (
1425            vec![vec![]; edges1.len() + 1],
1426            vec![vec![]; edges2.len() + 1],
1427        );
1428
1429        let mk_adjs = |tree: &mut [Vec<usize>], edges: &[Vec<i32>]| {
1430            for edge in edges {
1431                tree[edge[0] as usize].push(edge[1] as usize);
1432                tree[edge[1] as usize].push(edge[0] as usize);
1433            }
1434        };
1435
1436        for (tree, edges) in [(&mut tree1, &edges1), (&mut tree2, &edges2)] {
1437            mk_adjs(tree, edges);
1438            println!("-> {edges:?} => {tree:?}");
1439        }
1440
1441        fn color_nodes(
1442            v: usize,
1443            p: usize,
1444            depth: usize,
1445            colors: &mut [usize],
1446            tree: &[Vec<usize>],
1447        ) {
1448            colors[v] = depth & 1;
1449            for &u in &tree[v] {
1450                if u != p {
1451                    color_nodes(u, v, depth + 1, colors, tree);
1452                }
1453            }
1454        }
1455
1456        fn color_nodes_iterative(colors: &mut [usize], tree: &[Vec<usize>]) {
1457            use std::collections::VecDeque;
1458
1459            let mut q_bfs = VecDeque::from([(0, usize::MAX, 0)]);
1460            while let Some((v, p, depth)) = q_bfs.pop_front() {
1461                colors[v] = depth & 1;
1462                for &u in &tree[v] {
1463                    if u != p {
1464                        q_bfs.push_back((u, v, depth + 1));
1465                    }
1466                }
1467            }
1468        }
1469
1470        let mut colors1 = vec![0; tree1.len()];
1471        color_nodes(0, usize::MAX, 0, &mut colors1, &tree1);
1472
1473        let mut counts1 = [0; 2];
1474        counts1[0] = colors1.iter().filter(|&&color| color == 0).count();
1475        counts1[1] = tree1.len() - counts1[0];
1476
1477        println!("-> {counts1:?} {colors1:?}");
1478
1479        let mut colors2 = vec![0; tree2.len()];
1480        color_nodes_iterative(&mut colors2, &tree2);
1481
1482        let mut counts2 = [0; 2];
1483        counts2[0] = colors2.iter().filter(|&&color| color == 0).count();
1484        counts2[1] = tree2.len() - counts2[0];
1485
1486        println!("-> {counts2:?} {colors2:?}");
1487
1488        let mut xtrgs = vec![];
1489        for color in colors1 {
1490            xtrgs.push((counts1[color] + counts2[0].max(counts2[1])) as i32);
1491        }
1492
1493        xtrgs
1494    }
1495}
1496
1497#[cfg(test)]
1498mod tests;