@@ -58,22 +58,348 @@ distanceLimitedPathsExist.query(0, 5, 6); // 返回 false。从 0 到 5 之间
58
58
59
59
<!-- 这里可写通用的实现逻辑 -->
60
60
61
+ ** 方法一:可持久化并查集**
62
+
61
63
<!-- tabs:start -->
62
64
63
65
### ** Python3**
64
66
65
67
<!-- 这里可写当前语言的特殊实现逻辑 -->
66
68
67
69
``` python
70
+ class PersistentUnionFind :
71
+ def __init__ (self , n ):
72
+ self .rank = [0 ] * n
73
+ self .p = list (range (n))
74
+ self .version = [inf] * n
75
+
76
+ def find (self , x , t = inf):
77
+ if self .p[x] == x or self .version[x] >= t:
78
+ return x
79
+ return self .find(self .p[x], t)
80
+
81
+ def union (self , a , b , t ):
82
+ pa, pb = self .find(a), self .find(b)
83
+ if pa == pb:
84
+ return False
85
+ if self .rank[pa] > self .rank[pb]:
86
+ self .version[pb] = t
87
+ self .p[pb] = pa
88
+ else :
89
+ self .version[pa] = t
90
+ self .p[pa] = pb
91
+ if self .rank[pa] == self .rank[pb]:
92
+ self .rank[pb] += 1
93
+ return True
94
+
68
95
96
+ class DistanceLimitedPathsExist :
97
+ def __init__ (self , n : int , edgeList : List[List[int ]]):
98
+ self .puf = PersistentUnionFind(n)
99
+ edgeList.sort(key = lambda x : x[2 ])
100
+ for u, v, dis in edgeList:
101
+ self .puf.union(u, v, dis)
102
+
103
+ def query (self , p : int , q : int , limit : int ) -> bool :
104
+ return self .puf.find(p, limit) == self .puf.find(q, limit)
69
105
```
70
106
71
107
### ** Java**
72
108
73
109
<!-- 这里可写当前语言的特殊实现逻辑 -->
74
110
75
111
``` java
112
+ class PersistentUnionFind {
113
+ private final int inf = 1 << 30 ;
114
+ private int [] rank;
115
+ private int [] parent;
116
+ private int [] version;
117
+
118
+ public PersistentUnionFind (int n ) {
119
+ rank = new int [n];
120
+ parent = new int [n];
121
+ version = new int [n];
122
+ for (int i = 0 ; i < n; i++ ) {
123
+ parent[i] = i;
124
+ version[i] = inf;
125
+ }
126
+ }
127
+
128
+ public int find (int x , int t ) {
129
+ if (parent[x] == x || version[x] >= t) {
130
+ return x;
131
+ }
132
+ return find(parent[x], t);
133
+ }
134
+
135
+ public boolean union (int a , int b , int t ) {
136
+ int pa = find(a, inf);
137
+ int pb = find(b, inf);
138
+ if (pa == pb) {
139
+ return false ;
140
+ }
141
+ if (rank[pa] > rank[pb]) {
142
+ version[pb] = t;
143
+ parent[pb] = pa;
144
+ } else {
145
+ version[pa] = t;
146
+ parent[pa] = pb;
147
+ if (rank[pa] == rank[pb]) {
148
+ rank[pb]++ ;
149
+ }
150
+ }
151
+ return true ;
152
+ }
153
+ }
154
+
155
+ public class DistanceLimitedPathsExist {
156
+ private PersistentUnionFind puf;
157
+
158
+ public DistanceLimitedPathsExist (int n , int [][] edgeList ) {
159
+ puf = new PersistentUnionFind (n);
160
+ Arrays . sort(edgeList, (a, b) - > a[2 ] - b[2 ]);
161
+ for (var e : edgeList) {
162
+ puf. union(e[0 ], e[1 ], e[2 ]);
163
+ }
164
+ }
165
+
166
+ public boolean query (int p , int q , int limit ) {
167
+ return puf. find(p, limit) == puf. find(q, limit);
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Your DistanceLimitedPathsExist object will be instantiated and called as such:
173
+ * DistanceLimitedPathsExist obj = new DistanceLimitedPathsExist(n, edgeList);
174
+ * boolean param_1 = obj.query(p,q,limit);
175
+ */
176
+ ```
177
+
178
+ ### ** C++**
179
+
180
+ ``` cpp
181
+ class PersistentUnionFind {
182
+ private:
183
+ vector<int > rank;
184
+ vector<int > parent;
185
+ vector<int > version;
186
+
187
+ public:
188
+ PersistentUnionFind(int n)
189
+ : rank(n, 0)
190
+ , parent(n)
191
+ , version(n, INT_MAX) {
192
+ for (int i = 0; i < n; i++) {
193
+ parent[ i] = i;
194
+ }
195
+ }
196
+
197
+ int find(int x, int t) {
198
+ if (parent[x] == x || version[x] >= t) {
199
+ return x;
200
+ }
201
+ return find(parent[x], t);
202
+ }
203
+
204
+ bool unionSet (int a, int b, int t) {
205
+ int pa = find(a, INT_MAX);
206
+ int pb = find(b, INT_MAX);
207
+ if (pa == pb) {
208
+ return false;
209
+ }
210
+ if (rank[ pa] > rank[ pb] ) {
211
+ version[ pb] = t;
212
+ parent[ pb] = pa;
213
+ } else {
214
+ version[ pa] = t;
215
+ parent[ pa] = pb;
216
+ if (rank[ pa] == rank[ pb] ) {
217
+ rank[ pb] ++;
218
+ }
219
+ }
220
+ return true;
221
+ }
222
+ };
223
+
224
+ class DistanceLimitedPathsExist {
225
+ private:
226
+ PersistentUnionFind puf;
227
+
228
+ public:
229
+ DistanceLimitedPathsExist(int n, vector<vector<int >>& edgeList)
230
+ : puf(n) {
231
+ sort(edgeList.begin(), edgeList.end(),
232
+ [ ] (const vector<int >& a, const vector<int >& b) {
233
+ return a[ 2] < b[ 2] ;
234
+ });
235
+
236
+ for (const auto& edge : edgeList) {
237
+ puf.unionSet(edge[0], edge[1], edge[2]);
238
+ }
239
+ }
240
+
241
+ bool query(int p, int q, int limit) {
242
+ return puf.find(p, limit) == puf.find(q, limit);
243
+ }
244
+ };
245
+
246
+ /**
247
+ * Your DistanceLimitedPathsExist object will be instantiated and called as such:
248
+ * DistanceLimitedPathsExist* obj = new DistanceLimitedPathsExist(n, edgeList);
249
+ * bool param_1 = obj->query(p,q,limit);
250
+ * /
251
+ ```
252
+
253
+ ### **Go**
254
+
255
+ ```go
256
+ type PersistentUnionFind struct {
257
+ rank []int
258
+ parent []int
259
+ version []int
260
+ }
261
+
262
+ func NewPersistentUnionFind(n int) *PersistentUnionFind {
263
+ rank := make([]int, n)
264
+ parent := make([]int, n)
265
+ version := make([]int, n)
266
+
267
+ for i := 0; i < n; i++ {
268
+ parent[i] = i
269
+ }
270
+
271
+ return &PersistentUnionFind{
272
+ rank: rank,
273
+ parent: parent,
274
+ version: version,
275
+ }
276
+ }
277
+
278
+ func (uf *PersistentUnionFind) find(x int, t int) int {
279
+ if uf.parent[x] == x || uf.version[x] >= t {
280
+ return x
281
+ }
282
+ return uf.find(uf.parent[x], t)
283
+ }
284
+
285
+ func (uf *PersistentUnionFind) union(a, b, t int) bool {
286
+ pa := uf.find(a, int(^uint(0)>>1))
287
+ pb := uf.find(b, int(^uint(0)>>1))
288
+
289
+ if pa == pb {
290
+ return false
291
+ }
292
+
293
+ if uf.rank[pa] > uf.rank[pb] {
294
+ uf.version[pb] = t
295
+ uf.parent[pb] = pa
296
+ } else {
297
+ uf.version[pa] = t
298
+ uf.parent[pa] = pb
299
+ if uf.rank[pa] == uf.rank[pb] {
300
+ uf.rank[pb]++
301
+ }
302
+ }
303
+
304
+ return true
305
+ }
306
+
307
+ type DistanceLimitedPathsExist struct {
308
+ puf *PersistentUnionFind
309
+ }
310
+
311
+ func Constructor(n int, edgeList [][]int) DistanceLimitedPathsExist {
312
+ sort.Slice(edgeList, func(i, j int) bool {
313
+ return edgeList[i][2] < edgeList[j][2]
314
+ })
315
+
316
+ puf := NewPersistentUnionFind(n)
317
+
318
+ for _, edge := range edgeList {
319
+ puf.union(edge[0], edge[1], edge[2])
320
+ }
321
+
322
+ return DistanceLimitedPathsExist{
323
+ puf: puf,
324
+ }
325
+ }
326
+
327
+ func (dle *DistanceLimitedPathsExist) Query(p, q, limit int) bool {
328
+ return dle.puf.find(p, limit) == dle.puf.find(q, limit)
329
+ }
330
+
331
+ /**
332
+ * Your DistanceLimitedPathsExist object will be instantiated and called as such:
333
+ * obj := Constructor(n, edgeList);
334
+ * param_1 := obj.Query(p,q,limit);
335
+ */
336
+ ```
337
+
338
+ ### ** TypeScript**
339
+
340
+ ``` ts
341
+ class PersistentUnionFind {
342
+ private rank: number [];
343
+ private parent: number [];
344
+ private version: number [];
345
+
346
+ constructor (n : number ) {
347
+ this .rank = Array (n ).fill (0 );
348
+ this .parent = Array .from ({ length: n }, (_ , i ) => i );
349
+ this .version = Array (n ).fill (Infinity );
350
+ }
351
+
352
+ find(x : number , t : number ): number {
353
+ if (this .parent [x ] === x || this .version [x ] >= t ) {
354
+ return x ;
355
+ }
356
+ return this .find (this .parent [x ], t );
357
+ }
358
+
359
+ union(a : number , b : number , t : number ): boolean {
360
+ const pa = this .find (a , Infinity );
361
+ const pb = this .find (b , Infinity );
362
+
363
+ if (pa === pb ) {
364
+ return false ;
365
+ }
366
+
367
+ if (this .rank [pa ] > this .rank [pb ]) {
368
+ this .version [pb ] = t ;
369
+ this .parent [pb ] = pa ;
370
+ } else {
371
+ this .version [pa ] = t ;
372
+ this .parent [pa ] = pb ;
373
+ if (this .rank [pa ] === this .rank [pb ]) {
374
+ this .rank [pb ]++ ;
375
+ }
376
+ }
377
+
378
+ return true ;
379
+ }
380
+ }
381
+
382
+ class DistanceLimitedPathsExist {
383
+ private puf: PersistentUnionFind ;
384
+
385
+ constructor (n : number , edgeList : number [][]) {
386
+ this .puf = new PersistentUnionFind (n );
387
+ edgeList .sort ((a , b ) => a [2 ] - b [2 ]);
388
+ for (const [u, v, dis] of edgeList ) {
389
+ this .puf .union (u , v , dis );
390
+ }
391
+ }
392
+
393
+ query(p : number , q : number , limit : number ): boolean {
394
+ return this .puf .find (p , limit ) === this .puf .find (q , limit );
395
+ }
396
+ }
76
397
398
+ /**
399
+ * Your DistanceLimitedPathsExist object will be instantiated and called as such:
400
+ * var obj = new DistanceLimitedPathsExist(n, edgeList)
401
+ * var param_1 = obj.query(p,q,limit)
402
+ */
77
403
```
78
404
79
405
### ** ...**
0 commit comments