Skip to main content

graph/
lib.rs

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