Welcome to Subscribe On Youtube
1724. Checking Existence of Edge Length Limited Paths II
Description
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, and the graph may not be connected.
Implement the DistanceLimitedPathsExist
class:
DistanceLimitedPathsExist(int n, int[][] edgeList)
Initializes the class with an undirected graph.boolean query(int p, int q, int limit)
Returnstrue
if there exists a path fromp
toq
such that each edge on the path has a distance strictly less thanlimit
, and otherwisefalse
.
Example 1:
Input ["DistanceLimitedPathsExist", "query", "query", "query", "query"] [[6, [[0, 2, 4], [0, 3, 2], [1, 2, 3], [2, 3, 1], [4, 5, 5]]], [2, 3, 2], [1, 3, 3], [2, 0, 3], [0, 5, 6]] Output [null, true, false, true, false] Explanation DistanceLimitedPathsExist distanceLimitedPathsExist = new DistanceLimitedPathsExist(6, [[0, 2, 4], [0, 3, 2], [1, 2, 3], [2, 3, 1], [4, 5, 5]]); distanceLimitedPathsExist.query(2, 3, 2); // return true. There is an edge from 2 to 3 of distance 1, which is less than 2. distanceLimitedPathsExist.query(1, 3, 3); // return false. There is no way to go from 1 to 3 with distances strictly less than 3. distanceLimitedPathsExist.query(2, 0, 3); // return true. There is a way to go from 2 to 0 with distance < 3: travel from 2 to 3 to 0. distanceLimitedPathsExist.query(0, 5, 6); // return false. There are no paths from 0 to 5.
Constraints:
2 <= n <= 104
0 <= edgeList.length <= 104
edgeList[i].length == 3
0 <= ui, vi, p, q <= n-1
ui != vi
p != q
1 <= disi, limit <= 109
- At most
104
calls will be made toquery
.
Solutions
-
class PersistentUnionFind { private final int inf = 1 << 30; private int[] rank; private int[] parent; private int[] version; public PersistentUnionFind(int n) { rank = new int[n]; parent = new int[n]; version = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; version[i] = inf; } } public int find(int x, int t) { if (parent[x] == x || version[x] >= t) { return x; } return find(parent[x], t); } public boolean union(int a, int b, int t) { int pa = find(a, inf); int pb = find(b, inf); if (pa == pb) { return false; } if (rank[pa] > rank[pb]) { version[pb] = t; parent[pb] = pa; } else { version[pa] = t; parent[pa] = pb; if (rank[pa] == rank[pb]) { rank[pb]++; } } return true; } } public class DistanceLimitedPathsExist { private PersistentUnionFind puf; public DistanceLimitedPathsExist(int n, int[][] edgeList) { puf = new PersistentUnionFind(n); Arrays.sort(edgeList, (a, b) -> a[2] - b[2]); for (var e : edgeList) { puf.union(e[0], e[1], e[2]); } } public boolean query(int p, int q, int limit) { return puf.find(p, limit) == puf.find(q, limit); } } /** * Your DistanceLimitedPathsExist object will be instantiated and called as such: * DistanceLimitedPathsExist obj = new DistanceLimitedPathsExist(n, edgeList); * boolean param_1 = obj.query(p,q,limit); */
-
class PersistentUnionFind { private: vector<int> rank; vector<int> parent; vector<int> version; public: PersistentUnionFind(int n) : rank(n, 0) , parent(n) , version(n, INT_MAX) { for (int i = 0; i < n; i++) { parent[i] = i; } } int find(int x, int t) { if (parent[x] == x || version[x] >= t) { return x; } return find(parent[x], t); } bool unionSet(int a, int b, int t) { int pa = find(a, INT_MAX); int pb = find(b, INT_MAX); if (pa == pb) { return false; } if (rank[pa] > rank[pb]) { version[pb] = t; parent[pb] = pa; } else { version[pa] = t; parent[pa] = pb; if (rank[pa] == rank[pb]) { rank[pb]++; } } return true; } }; class DistanceLimitedPathsExist { private: PersistentUnionFind puf; public: DistanceLimitedPathsExist(int n, vector<vector<int>>& edgeList) : puf(n) { sort(edgeList.begin(), edgeList.end(), [](const vector<int>& a, const vector<int>& b) { return a[2] < b[2]; }); for (const auto& edge : edgeList) { puf.unionSet(edge[0], edge[1], edge[2]); } } bool query(int p, int q, int limit) { return puf.find(p, limit) == puf.find(q, limit); } }; /** * Your DistanceLimitedPathsExist object will be instantiated and called as such: * DistanceLimitedPathsExist* obj = new DistanceLimitedPathsExist(n, edgeList); * bool param_1 = obj->query(p,q,limit); */
-
class PersistentUnionFind: def __init__(self, n): self.rank = [0] * n self.p = list(range(n)) self.version = [inf] * n def find(self, x, t=inf): if self.p[x] == x or self.version[x] >= t: return x return self.find(self.p[x], t) def union(self, a, b, t): pa, pb = self.find(a), self.find(b) if pa == pb: return False if self.rank[pa] > self.rank[pb]: self.version[pb] = t self.p[pb] = pa else: self.version[pa] = t self.p[pa] = pb if self.rank[pa] == self.rank[pb]: self.rank[pb] += 1 return True class DistanceLimitedPathsExist: def __init__(self, n: int, edgeList: List[List[int]]): self.puf = PersistentUnionFind(n) edgeList.sort(key=lambda x: x[2]) for u, v, dis in edgeList: self.puf.union(u, v, dis) def query(self, p: int, q: int, limit: int) -> bool: return self.puf.find(p, limit) == self.puf.find(q, limit)
-
type PersistentUnionFind struct { rank []int parent []int version []int } func NewPersistentUnionFind(n int) *PersistentUnionFind { rank := make([]int, n) parent := make([]int, n) version := make([]int, n) for i := 0; i < n; i++ { parent[i] = i } return &PersistentUnionFind{ rank: rank, parent: parent, version: version, } } func (uf *PersistentUnionFind) find(x int, t int) int { if uf.parent[x] == x || uf.version[x] >= t { return x } return uf.find(uf.parent[x], t) } func (uf *PersistentUnionFind) union(a, b, t int) bool { pa := uf.find(a, int(^uint(0)>>1)) pb := uf.find(b, int(^uint(0)>>1)) if pa == pb { return false } if uf.rank[pa] > uf.rank[pb] { uf.version[pb] = t uf.parent[pb] = pa } else { uf.version[pa] = t uf.parent[pa] = pb if uf.rank[pa] == uf.rank[pb] { uf.rank[pb]++ } } return true } type DistanceLimitedPathsExist struct { puf *PersistentUnionFind } func Constructor(n int, edgeList [][]int) DistanceLimitedPathsExist { sort.Slice(edgeList, func(i, j int) bool { return edgeList[i][2] < edgeList[j][2] }) puf := NewPersistentUnionFind(n) for _, edge := range edgeList { puf.union(edge[0], edge[1], edge[2]) } return DistanceLimitedPathsExist{ puf: puf, } } func (dle *DistanceLimitedPathsExist) Query(p, q, limit int) bool { return dle.puf.find(p, limit) == dle.puf.find(q, limit) } /** * Your DistanceLimitedPathsExist object will be instantiated and called as such: * obj := Constructor(n, edgeList); * param_1 := obj.Query(p,q,limit); */
-
class PersistentUnionFind { private rank: number[]; private parent: number[]; private version: number[]; constructor(n: number) { this.rank = Array(n).fill(0); this.parent = Array.from({ length: n }, (_, i) => i); this.version = Array(n).fill(Infinity); } find(x: number, t: number): number { if (this.parent[x] === x || this.version[x] >= t) { return x; } return this.find(this.parent[x], t); } union(a: number, b: number, t: number): boolean { const pa = this.find(a, Infinity); const pb = this.find(b, Infinity); if (pa === pb) { return false; } if (this.rank[pa] > this.rank[pb]) { this.version[pb] = t; this.parent[pb] = pa; } else { this.version[pa] = t; this.parent[pa] = pb; if (this.rank[pa] === this.rank[pb]) { this.rank[pb]++; } } return true; } } class DistanceLimitedPathsExist { private puf: PersistentUnionFind; constructor(n: number, edgeList: number[][]) { this.puf = new PersistentUnionFind(n); edgeList.sort((a, b) => a[2] - b[2]); for (const [u, v, dis] of edgeList) { this.puf.union(u, v, dis); } } query(p: number, q: number, limit: number): boolean { return this.puf.find(p, limit) === this.puf.find(q, limit); } } /** * Your DistanceLimitedPathsExist object will be instantiated and called as such: * var obj = new DistanceLimitedPathsExist(n, edgeList) * var param_1 = obj.query(p,q,limit) */