главная Π½ΠΎΠ²ΠΎΠ΅ Π»ΡƒΡ‡ΡˆΠ΅Π΅ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ

Бсылка Π½Π° Π·Π°Π΄Π°Ρ‡Ρƒ β€” 3108. Minimum Cost Walk in Weighted Graph.

πŸ“Œ ОписаниС Π·Π°Π΄Π°Ρ‡ΠΈ

ΠŸΡ€ΠΈΠΌΠ΅Ρ€

πŸ’‘ ИдСя

πŸš€ Π”Π΅Ρ‚Π°Π»ΠΈ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π°

  1. ΠŸΠΎΡΡ‚Ρ€ΠΎΠ΅Π½ΠΈΠ΅ Π³Ρ€Π°Ρ„Π° Π² Π²ΠΈΠ΄Π΅ списка смСТности graph.
  2. Поиск ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ связности с использованиСм ΠΎΠ±Ρ…ΠΎΠ΄Π° Π² Π³Π»ΡƒΠ±ΠΈΠ½Ρƒ (DFS):
    • КаТдой ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π΅ присваиваСтся ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€.
    • ΠžΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ вычисляСтся ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ AND срСди всСх Ρ€Ρ‘Π±Π΅Ρ€ Π² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π΅.
  3. ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° запросов:
    • Если s ΠΈ t ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‚ Ρ€Π°Π·Π½Ρ‹ΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌ, ΠΎΡ‚Π²Π΅Ρ‚ -1.
    • Если s ΠΈ t ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‚ ΠΎΠ΄Π½ΠΎΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π΅, ΠΎΡ‚Π²Π΅Ρ‚ β€” ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ AND этой ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹.

⏳ Асимптотика

πŸ“ Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄

impl Solution {
    pub fn minimum_cost(n: i32, edges: Vec<Vec<i32>>, queries: Vec<Vec<i32>>) -> Vec<i32> {
        let n = n as usize;
        let mut graph = vec![Vec::new(); n];
        let mut component_id = vec![-1; n];

        // Build adjacency list
        for edge in edges {
            let (u, v, w) = (edge[0] as usize, edge[1] as usize, edge[2]);
            graph[u].push((v, w));
            graph[v].push((u, w));
        }

        let mut component_min_and = Vec::new();

        // Identify components and compute min AND for each
        for i in 0..n {
            if component_id[i] == -1 {
                component_min_and.push(Self::dfs(i, &graph, component_min_and.len() as i32, &mut component_id));
            }
        }

        // Process queries
        queries.into_iter()
            .map(|q| {
                let (s, t) = (component_id[q[0] as usize], component_id[q[1] as usize]);
                if s != t { -1 } else { component_min_and[s as usize] }
            }).collect()
    }

    /// Performs DFS to assign a component ID and compute the minimum bitwise AND in the component.
    fn dfs(start: usize, graph: &[Vec<(usize, i32)>], id: i32, component_id: &mut [i32]) -> i32 {
        let mut min_and = -1; // Tracks the minimum AND value in the component
        let mut stack = vec![start];

        while let Some(node) = stack.pop() {
            component_id[node] = id; // Mark node as part of this component

            for &(neighbor, weight) in &graph[node] {
                if component_id[neighbor] == -1 {
                    stack.push(neighbor); // Visit unvisited neighbors
                }
                min_and &= weight; // Update minimum AND value
            }
        }

        min_and
    }
}

Tags: #rust #algorithms #dfs #graph

β–² 2 β–Ό leetcoder ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΎ 25-03-2025

ПолСзно Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Ссли ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для разбиСния Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ связности ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ с Disjoint Set Unions, β€” ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰Π΅Π΅ Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅ Π² 2 Ρ€Π°Π·Π° быстрСС Π·Π° счёт Π±ΠΎΠ»Π΅Π΅ эффСктивных Π°Π»Π»ΠΎΠΊΠ°Ρ†ΠΈΠΉ памяти (Π½Π΅Ρ‚ нСобходимости ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ списки смСТности).

struct UnionFind {
    parent: Vec<usize>,
    size: Vec<usize>,
    min_and: Vec<i32>,
}

impl Solution {
    pub fn minimum_cost(n: i32, edges: Vec<Vec<i32>>, query: Vec<Vec<i32>>) -> Vec<i32> {
        let n = n as usize;
        let mut uf = UnionFind::new(n);

        // Process edges to construct the Union-Find structure
        for edge in &edges {
            let (u, v, w) = (edge[0] as usize, edge[1] as usize, edge[2]);
            uf.union(u, v, w);
        }

        // Process queries efficiently
        query.into_iter().map(|q| {
                let (s, t) = (uf.find(q[0] as usize), uf.find(q[1] as usize));
                if s == t { uf.min_and[s] } else { -1 }
            }).collect()
    }
}

impl UnionFind {
    fn new(n: usize) -> Self {
        UnionFind {
            parent: (0..n).collect(),
            size: vec![1; n],
            min_and: vec![-1; n],
        }
    }

    fn find(&mut self, x: usize) -> usize {
        if self.parent[x] != x {
            self.parent[x] = self.find(self.parent[x]); // Path compression
        }
        self.parent[x]
    }

    fn union(&mut self, a: usize, b: usize, weight: i32) {
        let mut root_a = self.find(a);
        let mut root_b = self.find(b);

        if root_a != root_b {
            // Union by size: attach the smaller tree under the larger tree
            if self.size[root_a] < self.size[root_b] {
                std::mem::swap(&mut root_a, &mut root_b);
            }
            self.parent[root_b] = root_a;
            self.size[root_a] += self.size[root_b];
            self.min_and[root_a] &= self.min_and[root_b];
        }

        // Update min_and for the new root
        self.min_and[root_a] &= weight;
    }
}
ΠΎΡ‚Π²Π΅Ρ‚ΠΈΡ‚ΡŒ