0% completed
Problem Statement
Given a weighted undirected graph with n
vertices numbered from 0
to n-1
, and an array edges
where edges[i] = [a, b, weight]
represents a bidirectional and weighted edge between nodes a
and b
.
A minimum spanning tree (MST) is a subset of the graph's edges that connects all vertices without cycles and with the smallest possible total edge weight.
An edge is critical if removing it would cause the MST's total weight to increase. An edge is pseudo-critical if it can be part of some MSTs but is not required in all MSTs.
Return a 2D array containing all the critical and pseudo-critical edges in the graph's MST.
Examples
Example 1
- Input: n = 4, edges = [[0, 1, 1], [1, 2, 2], [2, 3, 3], [0, 3, 4], [1, 3, 5]]
- Expected Output: [[0,1,2],[]]
- Justification: Edges [0, 1, 2] are critical as their removal increases the MST weight.
Example 2
- Input: n = 4, edges = [[0, 1, 1], [1, 2, 1], [2, 3, 1], [0, 3, 1], [0, 2, 2]]
- Expected Output: [[],[0,1,2,3]]
- Justification: Edges [0, 1, 2, 3] are pseudo-critical as they exists in some of MSTs.
Example 3
- Input: n = 6, edges = [[0, 1, 2], [1, 2, 3], [2, 3, 1], [3, 4, 4], [4, 5, 5], [0, 5, 6], [1, 4, 2]]
- Expected Output: [[0,1,2,4,6],[]]
- Justification: Edges [0,1,2,4,6] are critical as their removal increases the MST weight.
Constraints:
- 2 <= n <= 100
- 1 <= edges.length <= min(200, n * (n - 1) / 2)
- edges[i].length == 3
- 0 <= a<sub>i</sub> < b<sub>i</sub> < n
- 1 <= weight<sub>i</sub> <= 1000
- All pairs (a<sub>i</sub>, b<sub>i</sub>) are distinct.
Solution
To solve this problem, we need to find the minimum spanning tree (MST) of the graph using Kruskal's algorithm. This algorithm sorts the edges by weight and adds them to the MST, ensuring no cycles are formed until all vertices are connected. The first step is to determine the MST's total weight without removing any edges. Next, for each edge, we test its removal to check if the MST weight increases, indicating a critical edge. For pseudo-critical edges, we force their inclusion in the MST and check if the resulting tree's weight matches the original MST's weight.
This approach ensures we correctly identify all critical and pseudo-critical edges. By using Kruskal's algorithm, we efficiently handle edge weights and connectivity checks. This method is effective because it leverages the union-find data structure to detect cycles, ensuring optimal performance.
Step-by-Step Algorithm
-
Initialize Indexed Edges:
- Create a new list of edges where each edge is appended with its original index.
-
Sort Edges:
- Sort the edges by their weight in ascending order.
-
Calculate MST Weight:
- Use the Union-Find data structure to find the Minimum Spanning Tree (MST) and calculate its total weight.
- Initialize Union-Find with
nodes
and setstandardWeight
to 0. - Iterate over sorted edges and use
connect
to check if the edge can be added without forming a cycle. If yes, add the edge's weight tostandardWeight
.
-
Check for Critical and Pseudo-Critical Edges:
- Initialize the result list with two empty lists for critical and pseudo-critical edges.
-
Check Each Edge:
- For each edge:
- Ignore the Edge:
- Create a new Union-Find instance and ignore the current edge.
- Calculate the MST weight without the current edge.
- If the graph is disconnected or the MST weight increases, the edge is critical. Add it to the critical edges list.
- Force the Edge:
- Create a new Union-Find instance and force the current edge.
- Calculate the MST weight including the current edge.
- If the MST weight remains the same, the edge is pseudo-critical. Add it to the pseudo-critical edges list.
- Ignore the Edge:
- For each edge:
-
Return Result:
- Return the list containing critical and pseudo-critical edges.
Algorithm Walkthrough
Input:
n = 4
edges = [[0, 1, 1], [1, 2, 2], [2, 3, 3], [0, 3, 4], [1, 3, 5]]
-
Initialize Indexed Edges:
indexedEdges = [[0, 1, 1, 0], [1, 2, 2, 1], [2, 3, 3, 2], [0, 3, 4, 3], [1, 3, 5, 4]]
-
Sort Edges:
indexedEdges
after sorting by weight:[[0, 1, 1, 0], [1, 2, 2, 1], [2, 3, 3, 2], [0, 3, 4, 3], [1, 3, 5, 4]]
-
Calculate MST Weight:
- Initialize Union-Find for 4 nodes.
standardWeight = 0
- Add edge
[0, 1, 1, 0]
to MST.standardWeight = 1
- Add edge
[1, 2, 2, 1]
to MST.standardWeight = 3
- Add edge
[2, 3, 3, 2]
to MST.standardWeight = 6
- Edges
[0, 3, 4, 3]
and[1, 3, 5, 4]
form cycles, not added.
-
Check for Critical and Pseudo-Critical Edges:
- Initialize result:
result = [[], []]
- Initialize result:
-
Check Each Edge:
-
Edge [0, 1, 1, 0]:
- Ignore the Edge:
- Initialize Union-Find.
- MST without
[0, 1, 1, 0]
:- Add edge
[1, 2, 2, 1]
. MST weight = 2. - Add edge
[2, 3, 3, 2]
. MST weight = 5. - Add edge
[0, 3, 4, 3]
. MST weight = 9. - Graph remains connected.
- Add edge
- Since MST weight >
standardWeight
,[0, 1, 1, 0]
is critical.result[0] = [0]
- Force the Edge:
- Initialize Union-Find.
- MST with
[0, 1, 1, 0]
:- Add edge
[0, 1, 1, 0]
. MST weight = 1. - Add edge
[1, 2, 2, 1]
. MST weight = 3. - Add edge
[2, 3, 3, 2]
. MST weight = 6. - MST weight equals
standardWeight
, so not pseudo-critical.
- Add edge
- Ignore the Edge:
-
Edge [1, 2, 2, 1]:
- Ignore the Edge:
- Initialize Union-Find.
- MST without
[1, 2, 2, 1]
:- Add edge
[0, 1, 1, 0]
. MST weight = 1. - Add edge
[2, 3, 3, 2]
. MST weight = 4. - Add edge
[0, 3, 4, 3]
. MST weight = 8. - Graph remains connected.
- Add edge
- Since MST weight >
standardWeight
,[1, 2, 2, 1]
is critical.result[0] = [0, 1]
- Force the Edge:
- Initialize Union-Find.
- MST with
[1, 2, 2, 1]
:- Add edge
[1, 2, 2, 1]
. MST weight = 2. - Add edge
[0, 1, 1, 0]
. MST weight = 3. - Add edge
[2, 3, 3, 2]
. MST weight = 6. - MST weight equals
standardWeight
, so not pseudo-critical.
- Add edge
- Ignore the Edge:
-
Edge [2, 3, 3, 2]:
- Ignore the Edge:
- Initialize Union-Find.
- MST without
[2, 3, 3, 2]
:- Add edge
[0, 1, 1, 0]
. MST weight = 1. - Add edge
[1, 2, 2, 1]
. MST weight = 3. - Add edge
[0, 3, 4, 3]
. MST weight = 7. - Graph remains connected.
- Add edge
- Since MST weight >
standardWeight
,[2, 3, 3, 2]
is critical.result[0] = [0, 1, 2]
- Force the Edge:
- Initialize Union-Find.
- MST with
[2, 3, 3, 2]
:- Add edge
[2, 3, 3, 2]
. MST weight = 3. - Add edge
[0, 1, 1, 0]
. MST weight = 4. - Add edge
[1, 2, 2, 1]
. MST weight = 6. - MST weight equals
standardWeight
, so not pseudo-critical.
- Add edge
- Ignore the Edge:
-
Edge [0, 3, 4, 3]:
- Ignore the Edge:
- Initialize Union-Find.
- MST without
[0, 3, 4, 3]
:- Add edge
[0, 1, 1, 0]
. MST weight = 1. - Add edge
[1, 2, 2, 1]
. MST weight = 3. - Add edge
[2, 3, 3, 2]
. MST weight = 6. - MST weight equals
standardWeight
.
- Add edge
- Since MST weight equals
standardWeight
,[0, 3, 4, 3]
is not critical.
- Force the Edge:
- Initialize Union-Find.
- MST with
[0, 3, 4, 3]
:- Add edge
[0, 3, 4, 3]
. MST weight = 4. - Add edge
[0, 1, 1, 0]
. MST weight = 5. - Add edge
[1, 2, 2, 1]
. MST weight = 7. - MST weight >
standardWeight
, so not pseudo-critical.
- Add edge
- Ignore the Edge:
-
Edge [1, 3, 5, 4]:
- Ignore the Edge:
- Initialize Union-Find.
- MST without
[1, 3, 5, 4]
:- Add edge
[0, 1, 1, 0]
. MST weight = 1. - Add edge
[1, 2, 2, 1]
. MST weight = 3. - Add edge
[2, 3, 3, 2]
. MST weight = 6. - MST weight equals
standardWeight
.
- Add edge
- Since MST weight equals
standardWeight
,[1, 3, 5, 4]
is not critical.
- Force the Edge:
- Initialize Union-Find.
- MST with
[1, 3, 5, 4]
:- Add edge
[1, 3, 5, 4]
. MST weight = 5. - Add edge
[0, 1, 1, 0]
. MST weight = 6. - Add edge
[1, 2, 2, 1]
. MST weight = 8. - MST weight >
standardWeight
, so not pseudo-critical.
- Add edge
- Ignore the Edge:
-
-
Return Result:
- Return
result = [[0, 1, 2], []]
.
- Return
Code
Complexity Analysis
Time Complexity
- Sorting the Edges: Sorting the edges based on their weights takes O(E \log E), where (E) is the number of edges.
- Union-Find Operations:
- Union and Find Operations: Each union or find operation takes nearly constant time, O(\alpha(N)), where \alpha is the Inverse Ackermann function, which grows very slowly. Therefore, for (E) edges, the total time for union-find operations is O(E \alpha(N)).
- Iterating Through Edges for Critical and Pseudo-Critical Edges: We iterate through each edge and perform union-find operations for each edge, which is O(E^2 \alpha(N)).
Combining these, the overall time complexity is O(E \log E + E^2 \alpha(N)), which simplifies to O(E^2 \alpha(N)).
Space Complexity
- Storage for Union-Find Data Structures: We maintain multiple union-find data structures, each taking O(N) space.
- Storage for Indexed Edges: We maintain a list of indexed edges, taking O(E) space.
- Result Storage: The result list takes O(E) space.
Combining these, the overall space complexity is O(N + E).
.....
.....
.....
Table of Contents
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible