Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to check existence of edge length limited paths in Python
Given an undirected weighted graph with n nodes and an edgeList where each edge is represented as (u, v, w) indicating a path from node u to node v with distance w. We also have queries in the format (p, q, lim) asking whether there exists a path from node p to node q with total distance less than lim.
This problem can be efficiently solved using the Union-Find (Disjoint Set Union) data structure combined with sorting techniques.
Algorithm Overview
The approach involves:
- Sort edges by weight in ascending order
- Sort queries by their limit value
- For each query, progressively add edges with weight less than the limit
- Use Union-Find to check if two nodes are connected
Implementation
def solve(n, edgeList, queries):
# Initialize Union-Find structure
parent = [i for i in range(n + 1)]
rank = [0 for i in range(n + 1)]
def find(parent, x):
if parent[x] == x:
return x
parent[x] = find(parent, parent[x]) # Path compression
return parent[x]
def union(parent, a, b):
root_a = find(parent, a)
root_b = find(parent, b)
if root_a == root_b:
return
# Union by rank
if rank[root_a] < rank[root_b]:
parent[root_a] = root_b
elif rank[root_a] > rank[root_b]:
parent[root_b] = root_a
else:
parent[root_b] = root_a
rank[root_a] += 1
# Sort edges by weight
edgeList.sort(key=lambda x: x[2])
# Prepare result array and sort queries by limit
result = [False] * len(queries)
indexed_queries = [[i, query] for i, query in enumerate(queries)]
indexed_queries.sort(key=lambda x: x[1][2])
edge_index = 0
for query_idx, (p, q, limit) in indexed_queries:
# Add all edges with weight < limit
while edge_index < len(edgeList) and edgeList[edge_index][2] < limit:
u, v, weight = edgeList[edge_index]
union(parent, u, v)
edge_index += 1
# Check if p and q are connected
result[query_idx] = find(parent, p) == find(parent, q)
return result
# Test the function
n = 4
edgeList = [(1, 2, 16), (1, 3, 8), (2, 4, 3), (2, 3, 6), (4, 3, 3)]
queries = [(1, 4, 12), (2, 3, 3), (1, 2, 15)]
print(solve(n, edgeList, queries))
[True, False, True]
How It Works
Let's trace through the example:
Sorted edges by weight: [(2,4,3), (4,3,3), (2,3,6), (1,3,8), (1,2,16)]
Sorted queries by limit: [(2,3,3), (1,4,12), (1,2,15)]
- Query (2,3,3): No edges with weight < 3, so nodes 2 and 3 are not connected ? False
- Query (1,4,12): Add edges with weight < 12: (2,4,3), (4,3,3), (2,3,6), (1,3,8). Path 1?3?4 exists ? True
- Query (1,2,15): All previous edges remain, path 1?3?2 exists ? True
Time Complexity
| Operation | Time Complexity |
|---|---|
| Sorting edges | O(E log E) |
| Sorting queries | O(Q log Q) |
| Union-Find operations | O((E + Q) ?(n)) |
| Total | O(E log E + Q log Q) |
Where E is the number of edges, Q is the number of queries, and ? is the inverse Ackermann function.
Conclusion
This solution efficiently handles multiple path existence queries by combining Union-Find with sorting. The key insight is processing queries in order of increasing limits to avoid redundant edge processing.
---