Power Grid Maintenance

medium union-find graph heap

Problem

c power stations (ids 1…c) are linked by bidirectional cables in connections; directly or indirectly connected stations form a power grid. All stations start online. Process queries: [1, x] is a maintenance check — if x is online it answers itself, otherwise the online station with the smallest id in x's grid answers, or -1 if its grid has none online. [2, x] takes station x offline. Return the answers to every [1, x] query in order.

Inputc = 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]
All five stations form one grid. [1,3] → 3 is online. [2,1] offline. [1,1] → smallest online is 2. [2,2] offline. [1,2] → smallest online is 3.

import heapq

def processQueries(c, connections, queries):
    parent = list(range(c + 1))
    def find(x):
        while parent[x] != x:
            parent[x] = parent[parent[x]]   # path compression
            x = parent[x]
        return x
    for u, v in connections:                # union connected stations
        parent[find(u)] = find(v)
    heaps = {}                              # component root -> min-heap of ids
    for s in range(1, c + 1):
        heaps.setdefault(find(s), []).append(s)
    for h in heaps.values():
        heapq.heapify(h)
    online = [True] * (c + 1)
    res = []
    for t, x in queries:
        if t == 2:
            online[x] = False               # take station x offline
        elif online[x]:
            res.append(x)                   # x answers its own check
        else:
            h = heaps[find(x)]
            while h and not online[h[0]]:    # discard offline tops lazily
                heapq.heappop(h)
            res.append(h[0] if h else -1)
    return res
function processQueries(c, connections, queries) {
  const parent = Array.from({ length: c + 1 }, (_, i) => i);
  function find(x) {
    while (parent[x] !== x) { parent[x] = parent[parent[x]]; x = parent[x]; }
    return x;                              // root with path compression
  }
  for (const [u, v] of connections) parent[find(u)] = find(v);
  const heaps = new Map();                 // root -> min-heap of ids
  for (let s = 1; s <= c; s++) {
    const r = find(s);
    if (!heaps.has(r)) heaps.set(r, new MinHeap());
    heaps.get(r).push(s);
  }
  const online = new Array(c + 1).fill(true);
  const res = [];
  for (const [t, x] of queries) {
    if (t === 2) { online[x] = false; }     // take station x offline
    else if (online[x]) { res.push(x); }    // x answers its own check
    else {
      const h = heaps.get(find(x));
      while (h.size() && !online[h.peek()]) h.pop();  // drop offline tops
      res.push(h.size() ? h.peek() : -1);
    }
  }
  return res;
}
int[] processQueries(int c, int[][] connections, int[][] queries) {
    int[] parent = new int[c + 1];
    for (int i = 0; i <= c; i++) parent[i] = i;
    for (int[] e : connections) parent[find(parent, e[0])] = find(parent, e[1]);
    Map<Integer, PriorityQueue<Integer>> heaps = new HashMap<>();
    for (int s = 1; s <= c; s++)            // group ids by component root
        heaps.computeIfAbsent(find(parent, s), k -> new PriorityQueue<>()).add(s);
    boolean[] online = new boolean[c + 1];
    Arrays.fill(online, true);
    List<Integer> res = new ArrayList<>();
    for (int[] q : queries) {
        int x = q[1];
        if (q[0] == 2) online[x] = false;   // take station x offline
        else if (online[x]) res.add(x);     // x answers its own check
        else {
            PriorityQueue<Integer> h = heaps.get(find(parent, x));
            while (!h.isEmpty() && !online[h.peek()]) h.poll();  // drop offline
            res.add(h.isEmpty() ? -1 : h.peek());
        }
    }
    return res.stream().mapToInt(Integer::intValue).toArray();
}
int find(int[] p, int x) { while (p[x] != x) { p[x] = p[p[x]]; x = p[x]; } return x; }
vector<int> processQueries(int c, vector<vector<int>>& connections,
                           vector<vector<int>>& queries) {
    vector<int> parent(c + 1);
    iota(parent.begin(), parent.end(), 0);
    function<int(int)> find = [&](int x) {
        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }
        return x;                           // root with path compression
    };
    for (auto& e : connections) parent[find(e[0])] = find(e[1]);
    unordered_map<int, priority_queue<int, vector<int>, greater<int>>> heaps;
    for (int s = 1; s <= c; s++) heaps[find(s)].push(s);  // min-heaps per grid
    vector<bool> online(c + 1, true);
    vector<int> res;
    for (auto& q : queries) {
        int x = q[1];
        if (q[0] == 2) online[x] = false;   // take station x offline
        else if (online[x]) res.push_back(x);
        else {
            auto& h = heaps[find(x)];
            while (!h.empty() && !online[h.top()]) h.pop();  // drop offline tops
            res.push_back(h.empty() ? -1 : h.top());
        }
    }
    return res;
}
Time: O((c + q) log c) Space: O(c)