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)
Returns true
if there exists a path from p
to q
such that each edge on the path has a distance strictly less than limit
, and otherwise false
.
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 to query
.
Solutions#
Solution 1#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| 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)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
| 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);
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
| 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);
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
| 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);
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| 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)
*/
|