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:
{1, 2, 3, 4, 5}
are online and form a single power grid.[1,3]
: Station 3 is online, so the maintenance check is resolved by station 3.[2,1]
: Station 1 goes offline. The remaining online stations are {2, 3, 4, 5}
.[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.[2,2]
: Station 2 goes offline. The remaining online stations are {3, 4, 5}
.[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:
[1,1]
: Station 1 is online in its isolated grid, so the maintenance check is resolved by station 1.[2,1]
: Station 1 goes offline.[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
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force strategy is to exhaustively check every single possible maintenance plan. We will identify all the non-essential power lines, consider every possible combination of them to disconnect, and for each combination, we'll count how many separate power grids are created.
Here's how the algorithm would work step-by-step:
def find_minimum_cost_brute_force(number_of_cities, available_power_lines):
minimum_total_cost = 999999999
# To guarantee finding the optimal grid, we must test every possible combination of power lines.
for subset_size in range(1, len(available_power_lines) + 1):
# Note: This code assumes 'itertools.combinations' is available.
for power_line_subset in itertools.combinations(available_power_lines, subset_size):
# To be a valid solution, a set of lines must connect all cities into one network.
parent_map = list(range(number_of_cities))
number_of_components = number_of_cities
def find_root(city_index):
if parent_map[city_index] == city_index:
return city_index
parent_map[city_index] = find_root(parent_map[city_index])
return parent_map[city_index]
def union_components(city_one, city_two):
nonlocal number_of_components
root_one = find_root(city_one)
root_two = find_root(city_two)
if root_one != root_two:
parent_map[root_two] = root_one
number_of_components -= 1
for line_city_one, line_city_two, _ in power_line_subset:
union_components(line_city_one, line_city_two)
# We only calculate the cost for valid grids that link every city into a single component.
if number_of_components == 1:
current_subset_cost = sum(cost for _, _, cost in power_line_subset)
# The total cost is updated if this valid grid is cheaper than the best one found so far.
minimum_total_cost = min(minimum_total_cost, current_subset_cost)
if minimum_total_cost == 999999999:
return -1
else:
return minimum_total_cost
Instead of trying to figure out the entire grid layout at once, the best approach is to build it one piece at a time. We can do this by repeatedly adding the cheapest possible power line that doesn't create a redundant connection, guaranteeing the lowest total cost in the end.
Here's how the algorithm would work step-by-step:
def power_grid_maintenance(number_of_cities, all_potential_lines):
parent_of_city = list(range(number_of_cities))
def find_island_representative(city_index):
if parent_of_city[city_index] == city_index:
return city_index
# Path compression makes subsequent lookups for this city and its children much faster.
parent_of_city[city_index] = find_island_representative(parent_of_city[city_index])
return parent_of_city[city_index]
# Sort all potential connections by cost to greedily evaluate the cheapest options first.
all_potential_lines.sort(key=lambda line_details: line_details[2])
total_maintenance_cost = 0
number_of_lines_built = 0
for city_one, city_two, connection_cost in all_potential_lines:
root_for_city_one = find_island_representative(city_one)
root_for_city_two = find_island_representative(city_two)
# A connection is only useful if it joins two previously disconnected grid sections.
if root_for_city_one != root_for_city_two:
total_maintenance_cost += connection_cost
# Merge the two separate islands, effectively building the new power line.
parent_of_city[root_for_city_two] = root_for_city_one
number_of_lines_built += 1
if number_of_lines_built == number_of_cities - 1:
break
return total_maintenance_cost
Case | How to Handle |
---|---|
The `connections` array is empty, resulting in `c` separate power grids, each with a single station. | The underlying graph data structure, such as a Disjoint Set Union, correctly initializes each station as an independent component. |
All stations in a specific power grid are turned offline before a type 1 query is made for a station in that grid. | The solution must return -1 for such a query, which is managed by tracking the smallest operational station per grid and using a sentinel value for depleted grids. |
A station is taken offline multiple times via repeated type 2 queries. | The station's state is idempotent, so the solution correctly handles this by simply maintaining its offline status without error. |
The `queries` array contains only type 1 (maintenance check) queries and no type 2 queries. | In this case, all stations remain online, and for any query `[1, x]`, the solution will correctly return `x`. |
All `c` stations are connected and form a single, large power grid. | The solution's graph representation will group all stations under one root, and all queries will be resolved within this single component. |
The system consists of only one station (`c=1`) with no connections. | The solution correctly handles this base case, where the single station is its own grid and can only be online or offline. |
Station IDs are 1-based (from 1 to c), which can lead to off-by-one errors with 0-indexed arrays. | The implementation must consistently adjust for the 1-based indexing, typically by using arrays of size c+1 or by subtracting 1 from IDs. |
The `queries` input array is empty. | The solution should gracefully handle this by returning an empty results array, as there are no type 1 queries to process. |