Welcome to Subscribe On Youtube

3607. Power Grid Maintenance

Description

You are given an integer c representing c power stations, each with a unique identifier id from 1 to c (1‑based indexing).

These stations are interconnected via n bidirectional cables, represented by a 2D array connections, where each element connections[i] = [ui, vi] indicates a connection between station ui and station vi. Stations that are directly or indirectly connected form a power grid.

Initially, all stations are online (operational).

You are also given a 2D array queries, where each query is one of the following two types:

  • [1, x]: A maintenance check is requested for station x. If station x is online, it resolves the check by itself. If station x is offline, the check is resolved by the operational station with the smallest id in the same power grid as x. If no operational station exists in that grid, return -1.

  • [2, x]: Station x goes offline (i.e., it becomes non-operational).

Return an array of integers representing the results of each query of type [1, x] in the order they appear.

Note: The power grid preserves its structure; an offline (non‑operational) node remains part of its grid and taking it offline does not alter connectivity.

 

Example 1:

Input: c = 5, connections = [[1,2],[2,3],[3,4],[4,5]], queries = [[1,3],[2,1],[1,1],[2,2],[1,2]]

Output: [3,2,3]

Explanation:

  • Initially, all stations {1, 2, 3, 4, 5} are online and form a single power grid.
  • Query [1,3]: Station 3 is online, so the maintenance check is resolved by station 3.
  • Query [2,1]: Station 1 goes offline. The remaining online stations are {2, 3, 4, 5}.
  • Query [1,1]: Station 1 is offline, so the check is resolved by the operational station with the smallest id among {2, 3, 4, 5}, which is station 2.
  • Query [2,2]: Station 2 goes offline. The remaining online stations are {3, 4, 5}.
  • Query [1,2]: Station 2 is offline, so the check is resolved by the operational station with the smallest id among {3, 4, 5}, which is station 3.

Example 2:

Input: c = 3, connections = [], queries = [[1,1],[2,1],[1,1]]

Output: [1,-1]

Explanation:

  • There are no connections, so each station is its own isolated grid.
  • Query [1,1]: Station 1 is online in its isolated grid, so the maintenance check is resolved by station 1.
  • Query [2,1]: Station 1 goes offline.
  • Query [1,1]: Station 1 is offline and there are no other stations in its grid, so the result is -1.

 

Constraints:

  • 1 <= c <= 105
  • 0 <= n == connections.length <= min(105, c * (c - 1) / 2)
  • connections[i].length == 2
  • 1 <= ui, vi <= c
  • ui != vi
  • 1 <= queries.length <= 2 * 105
  • queries[i].length == 2
  • queries[i][0] is either 1 or 2.
  • 1 <= queries[i][1] <= c

Solutions

Solution 1

  • class UnionFind {
        private final int[] p;
        private final int[] size;
    
        public UnionFind(int n) {
            p = new int[n];
            size = new int[n];
            for (int i = 0; i < n; ++i) {
                p[i] = i;
                size[i] = 1;
            }
        }
    
        public int find(int x) {
            if (p[x] != x) {
                p[x] = find(p[x]);
            }
            return p[x];
        }
    
        public boolean union(int a, int b) {
            int pa = find(a), pb = find(b);
            if (pa == pb) {
                return false;
            }
            if (size[pa] > size[pb]) {
                p[pb] = pa;
                size[pa] += size[pb];
            } else {
                p[pa] = pb;
                size[pb] += size[pa];
            }
            return true;
        }
    }
    
    class Solution {
        public int[] processQueries(int c, int[][] connections, int[][] queries) {
            UnionFind uf = new UnionFind(c + 1);
            for (int[] e : connections) {
                uf.union(e[0], e[1]);
            }
    
            TreeSet<Integer>[] st = new TreeSet[c + 1];
            Arrays.setAll(st, k -> new TreeSet<>());
            for (int i = 1; i <= c; i++) {
                int root = uf.find(i);
                st[root].add(i);
            }
    
            List<Integer> ans = new ArrayList<>();
            for (int[] q : queries) {
                int a = q[0], x = q[1];
                int root = uf.find(x);
    
                if (a == 1) {
                    if (st[root].contains(x)) {
                        ans.add(x);
                    } else if (!st[root].isEmpty()) {
                        ans.add(st[root].first());
                    } else {
                        ans.add(-1);
                    }
                } else {
                    st[root].remove(x);
                }
            }
    
            return ans.stream().mapToInt(Integer::intValue).toArray();
        }
    }
    
    
  • class UnionFind {
    public:
        UnionFind(int n) {
            p = vector<int>(n);
            size = vector<int>(n, 1);
            iota(p.begin(), p.end(), 0);
        }
    
        bool unite(int a, int b) {
            int pa = find(a), pb = find(b);
            if (pa == pb) {
                return false;
            }
            if (size[pa] > size[pb]) {
                p[pb] = pa;
                size[pa] += size[pb];
            } else {
                p[pa] = pb;
                size[pb] += size[pa];
            }
            return true;
        }
    
        int find(int x) {
            if (p[x] != x) {
                p[x] = find(p[x]);
            }
            return p[x];
        }
    
    private:
        vector<int> p, size;
    };
    
    class Solution {
    public:
        vector<int> processQueries(int c, vector<vector<int>>& connections, vector<vector<int>>& queries) {
            UnionFind uf(c + 1);
            for (auto& e : connections) {
                uf.unite(e[0], e[1]);
            }
    
            vector<set<int>> st(c + 1);
            for (int i = 1; i <= c; i++) {
                st[uf.find(i)].insert(i);
            }
    
            vector<int> ans;
            for (auto& q : queries) {
                int a = q[0], x = q[1];
                int root = uf.find(x);
                if (a == 1) {
                    if (st[root].count(x)) {
                        ans.push_back(x);
                    } else if (!st[root].empty()) {
                        ans.push_back(*st[root].begin());
                    } else {
                        ans.push_back(-1);
                    }
                } else {
                    st[root].erase(x);
                }
            }
            return ans;
        }
    };
    
    
  • class UnionFind:
        def __init__(self, n):
            self.p = list(range(n))
            self.size = [1] * n
    
        def find(self, x):
            if self.p[x] != x:
                self.p[x] = self.find(self.p[x])
            return self.p[x]
    
        def union(self, a, b):
            pa, pb = self.find(a), self.find(b)
            if pa == pb:
                return False
            if self.size[pa] > self.size[pb]:
                self.p[pb] = pa
                self.size[pa] += self.size[pb]
            else:
                self.p[pa] = pb
                self.size[pb] += self.size[pa]
            return True
    
    
    class Solution:
        def processQueries(
            self, c: int, connections: List[List[int]], queries: List[List[int]]
        ) -> List[int]:
            uf = UnionFind(c + 1)
            for u, v in connections:
                uf.union(u, v)
            st = [SortedList() for _ in range(c + 1)]
            for i in range(1, c + 1):
                st[uf.find(i)].add(i)
            ans = []
            for a, x in queries:
                root = uf.find(x)
                if a == 1:
                    if x in st[root]:
                        ans.append(x)
                    elif len(st[root]):
                        ans.append(st[root][0])
                    else:
                        ans.append(-1)
                else:
                    st[root].discard(x)
            return ans
    
    

All Problems

All Solutions