Power Grid Maintenance solution and explanation
9 more videos on this problem
Power Grid Maintenance | Simplest Solution | Intuition | Dry Run | Leetcode 3607 | codestorywithMIKcodestorywithMIK · 45:01 · 6K views
Power Grid Maintenance - Leetcode 3607 - PythonNeetCodeIO · 20:04 · 6K views
Power Grid Maintenance | Using DSU | Simplest Explanation | Leetcode 3607 | codestorywithMIKcodestorywithMIK · 30:43 · 2K views
Power Grid Maintenance | LeetCode 3607 | Complete Intuition ExplainedSanyam IIT Guwahati · 21:22 · 2K views
LeetCode 3607. Power Grid Maintenance | DFS | Set | Graph | Medium | O(NLogN)Leet's Code · 24:27 · 1K views
3607. Power Grid Maintenance (Leetcode Medium)Programming Live with Larry · 13:22 · 865 views
Daily Leetcode #2046: Nov 06, 2025 - 3607. Power Grid MaintenanceProgramming Live with Larry · 18:02 · 619 views
Power Grid Maintenance | Leetcode 3607 | DSA | HIndi Explanation | Code With DeepakCode with Deepak · 30:58 · 493 views
Power Grid Maintenance | LeetCode 3607 | Union-Find (DSU) | Java Code | Developer CoderDeveloper Coder · 31:54 · 334 views
3607. Power Grid Maintenance | Leetcode Daily - PythonLeetcode Daily · 11:17 · 310 views
The problem
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 stationx. If stationxis online, it resolves the check by itself. If stationxis offline, the check is resolved by the operational station with the smallestidin the same power grid asx. If no operational station exists in that grid, return -1. -
[2, x]: Stationxgoes 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 smallestidamong{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 smallestidamong{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 <= 1050 <= n == connections.length <= min(105, c * (c - 1) / 2)connections[i].length == 21 <= ui, vi <= cui != vi1 <= queries.length <= 2 * 105queries[i].length == 2queries[i][0]is either 1 or 2.1 <= queries[i][1] <= c
Approach overview
Problem Overview: You manage a power grid where cities (nodes) are connected by transmission lines (edges). As maintenance operations occur, connections change and queries ask about connectivity or available power sources. The task is to efficiently maintain the grid state and answer these queries without recomputing the entire graph each time.
Approach 1: Rebuild Connectivity with DFS/BFS (O(Q * (N + E)) time, O(N) space)
A straightforward solution treats each query independently. When the grid changes, rebuild the connectivity information by running a traversal such as Depth-First Search or Breadth-First Search. For each query, start from the requested node and explore reachable nodes using an adjacency list. This guarantees correctness but quickly becomes expensive because each update or query may trigger a full traversal of the graph.
Approach 2: Adjacency Tracking with Hash Structures (O((N + E) + Q log N) time, O(N + E) space)
Another improvement keeps adjacency lists in a Hash Table or map structure and only updates edges affected by maintenance operations. Queries still require checking component membership through traversal, but updates become cheaper because edge modifications are constant time. This approach works for smaller graphs but still struggles when queries are frequent since connectivity checks remain expensive.
Approach 3: Union-Find + Sorted Set (O((N + E) α(N) + Q log N) time, O(N) space)
The optimal approach models the grid as connected components using a Disjoint Set Union (Union-Find) structure. Each transmission line performs a union(a, b) operation, quickly merging two components using path compression and union by rank. To support maintenance queries that require retrieving a specific active node (for example, the smallest available station in a component), maintain an ordered set of nodes per component. When components merge, merge or update their sets so queries can retrieve the required element in O(log n) time.
The key insight: connectivity changes are handled by Union-Find in near constant time, while the ordered set efficiently tracks nodes that satisfy query constraints. Instead of recomputing the graph for every query, the algorithm maintains component-level metadata and performs fast lookups.
Recommended for interviews: The Union-Find + ordered set solution is what most interviewers expect for dynamic connectivity problems. A DFS/BFS rebuild shows you understand graph traversal, but the optimized solution demonstrates knowledge of Union Find, component merging, and efficient query handling in large graphs.
Solution
We can use Union-Find to maintain the connection relationships between power stations, thereby determining which grid each station belongs to. For each grid, we use a sorted set (such as SortedList in Python, TreeSet in Java, or std::set in C++) to store all online station IDs in that grid, allowing efficient querying and deletion of stations.
The specific steps are as follows:
- Initialize the Union-Find structure and process all connection relationships, merging connected stations into the same set.
- Create a sorted set for each grid, initially adding all station IDs to their corresponding grid's set.
- Iterate through the query list:
- For query
[1, x], first find the root node of the grid that stationxbelongs to, then check that grid's sorted set:- If station
xis online (exists in the set), returnx. - Otherwise, return the station with the smallest ID in the set (if the set is non-empty), otherwise return -1.
- If station
- For query
[2, x], find the root node of the grid that stationxbelongs to, and remove stationxfrom that grid's sorted set, indicating that the station is offline.
- For query
- Finally, return all query results of type
[1, x].
The time complexity is O((c + n + q) log c) and the space complexity is O(c), where c is the number of stations, and n and q are the number of connections and queries, respectively.
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 ansclass 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;
}
};Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| DFS/BFS Rebuild per Query | O(Q * (N + E)) | O(N) | Small graphs or when queries are very limited |
| Adjacency + Hash Structures | O((N + E) + Q log N) | O(N + E) | Moderate input sizes with infrequent connectivity checks |
| Union-Find + Sorted Set | O((N + E) α(N) + Q log N) | O(N) | Large graphs with many updates and connectivity queries |
Frequently asked questions
Is Power Grid Maintenance easy or hard?
Power Grid Maintenance is generally considered a medium-level problem. The challenge comes from recognizing that repeated graph traversals are too slow and switching to a Union-Find based design that maintains connectivity efficiently while supporting ordered queries.
Power Grid Maintenance Python/Java solution
A typical implementation uses a Union-Find class with path compression and union by rank. Each component maintains an ordered structure such as TreeSet in Java, sorted containers in Python, or set + heap variants depending on the requirement. The same logic translates easily across Python, Java, C++, and Go.
How to solve Power Grid Maintenance in O(n)?
Pure O(n) is typically not achievable because dynamic queries require ordered lookups or updates. However, the core connectivity operations can be made almost constant using Union-Find with path compression. The remaining cost comes from ordered set operations, resulting in roughly O((n + q) log n) overall complexity.
What is the best approach for Power Grid Maintenance?
The most efficient approach uses Union-Find (Disjoint Set Union) combined with an ordered set. Union-Find maintains connected components of the power grid in near constant time using path compression. The ordered set tracks nodes within each component so queries can retrieve the required station in O(log n) time.
Is Power Grid Maintenance asked at Google/Amazon/Meta?
Problems involving dynamic graph connectivity, Union-Find, and component queries frequently appear in interviews at companies like Google, Amazon, and Meta. Variants include maintaining network connectivity, detecting connected components, and handling online graph updates.
What data structure is used in Power Grid Maintenance?
The primary data structure is Union-Find (Disjoint Set Union) for tracking connected components. An ordered set or balanced tree structure is often used alongside it to store nodes within each component and support efficient retrieval operations.
What is the time complexity of Power Grid Maintenance?
The optimal solution runs in O((N + E) α(N) + Q log N) time, where α(N) is the inverse Ackermann function from Union-Find operations. Each union or find operation is nearly constant, while ordered set operations such as insert or lookup take O(log n). Space complexity is O(N).
