An undirected graph of n nodes is defined by edgeList, where edgeList[i] = [ui, vi, disi] denotes an edge between nodes ui and vi with distance disi. Note that there may be multiple edges between two nodes.
Given an array queries, where queries[j] = [pj, qj, limitj], your task is to determine for each queries[j] whether there is a path between pj and qj such that each edge on the path has a distance strictly less thanlimitj .
Return a boolean arrayanswer, whereanswer.length == queries.lengthand thejthvalue ofansweristrueif there is a path forqueries[j]istrue, andfalseotherwise.
Input:
n = 3, edgeList = [[0,1,2],[1,2,4],[2,0,8],[1,0,16]], queries = [[0,1,2],[0,2,5]]
Output:
[false,true]
Explanation: The above figure shows the given graph. Note that there are two overlapping edges between 0 and 1 with distances 2 and 16.
For the first query, between 0 and 1 there is no path where each distance is less than 2, thus we return false for this query.
For the second query, there is a path (0 -> 1 -> 2) of two edges with distances less than 5, thus we return true for this query.
Example 2:
1
2
3
4
5
Input:
n = 5, edgeList = [[0,1,10],[1,2,5],[2,3,9],[3,4,13]], queries = [[0,4,14],[1,4,13]]
Output:
[true,false]
Explanation: The above figure shows the given graph.
The key idea is to process all queries and edges in increasing order of their limits/weights. As we process edges with weights less than the current query’s limit, we use Union-Find to connect nodes. For each query, we check if the two nodes are connected in the current Union-Find structure.
classSolution {
publicboolean[]distanceLimitedPathsExist(int n, int[][] edgeList, int[][] queries) {
int m = queries.length;
int[] idx =newint[m];
for (int i = 0; i < m; i++) idx[i]= i;
Arrays.sort(idx, (a, b) -> Integer.compare(queries[a][2], queries[b][2]));
Arrays.sort(edgeList, Comparator.comparingInt(a -> a[2]));
int[] par =newint[n];
for (int i = 0; i < n; i++) par[i]= i;
java.util.function.IntUnaryOperator find =new java.util.function.IntUnaryOperator() {
publicintapplyAsInt(int x) { return par[x]== x ? x : (par[x]= applyAsInt(par[x])); }
};
boolean[] ans =newboolean[m];
int j = 0;
for (int i : idx) {
while (j < edgeList.length&& edgeList[j][2]< queries[i][2]) {
int u = edgeList[j][0], v = edgeList[j][1];
par[find.applyAsInt(u)]= find.applyAsInt(v);
j++;
}
ans[i]= find.applyAsInt(queries[i][0]) == find.applyAsInt(queries[i][1]);
}
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classSolution {
fundistanceLimitedPathsExist(n: Int, edgeList: Array<IntArray>, queries: Array<IntArray>): BooleanArray {
val idx = queries.indices.sortedBy { queries[it][2] }
edgeList.sortBy { it[2] }
val par = IntArray(n) { it }
funfind(x: Int): Int = if (par[x] == x) x else { par[x] = find(par[x]); par[x] }
val ans = BooleanArray(queries.size)
var j = 0for (i in idx) {
while (j < edgeList.size && edgeList[j][2] < queries[i][2]) {
val(u, v) = edgeList[j]
par[find(u)] = find(v)
j++ }
ans[i] = find(queries[i][0]) == find(queries[i][1])
}
return ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classSolution:
defdistanceLimitedPathsExist(self, n: int, edgeList: list[list[int]], queries: list[list[int]]) -> list[bool]:
idx = sorted(range(len(queries)), key=lambda i: queries[i][2])
edgeList.sort(key=lambda x: x[2])
par = list(range(n))
deffind(x):
if par[x] != x:
par[x] = find(par[x])
return par[x]
ans = [False] * len(queries)
j =0for i in idx:
while j < len(edgeList) and edgeList[j][2] < queries[i][2]:
u, v = edgeList[j][0], edgeList[j][1]
par[find(u)] = find(v)
j +=1 ans[i] = find(queries[i][0]) == find(queries[i][1])
return ans
⏰ Time complexity: O((n + m + q) * α(n)), where n is the number of nodes, m is the number of edges, q is the number of queries, and α is the inverse Ackermann function for Union-Find operations.
🧺 Space complexity: O(n + m + q), for the parent array, edge list, and queries.