# 并查集模板 fa = list(range(n)) deffind(x: int) -> int: if fa[x] != x: fa[x] = find(fa[x]) return fa[x] defmerge(from_: int, to: int) -> None: fa[find(from_)] = find(to)
ans, k = [False] * len(queries), 0 # 查询的下标按照 limit 从小到大排序,方便离线 for i, (p, q, limit) insorted(enumerate(queries), key=lambda p: p[1][2]): while k < len(edgeList) and edgeList[k][2] < limit: merge(edgeList[k][0], edgeList[k][1]) k += 1 ans[i] = find(p) == find(q) return ans
publicclassSolution { publicbool[] DistanceLimitedPathsExist(int n, int[][] edgeList, int[][] queries) { Array.Sort(edgeList, (a, b) => a[2] - b[2]);
int[] index = newint[queries.Length]; for (int i = 0; i < queries.Length; i++) { index[i] = i; } Array.Sort(index, (a, b) => queries[a][2] - queries[b][2]);
int[] uf = newint[n]; for (int i = 0; i < n; i++) { uf[i] = i; } bool[] res = newbool[queries.Length]; int k = 0; foreach (int i in index) { while (k < edgeList.Length && edgeList[k][2] < queries[i][2]) { Merge(uf, edgeList[k][0], edgeList[k][1]); k++; } res[i] = Find(uf, queries[i][0]) == Find(uf, queries[i][1]); } return res; }
publicintFind(int[] uf, int x) { if (uf[x] == x) { return x; } return uf[x] = Find(uf, uf[x]); }
publicvoidMerge(int[] uf, int x, int y) { x = Find(uf, x); y = Find(uf, y); uf[y] = x; } }
// 并查集模板 fa := make([]int, n) for i := range fa { fa[i] = i } var find func(int)int find = func(x int)int { if fa[x] != x { fa[x] = find(fa[x]) } return fa[x] } merge := func(from, to int) { fa[find(from)] = find(to) }
for i := range queries { queries[i] = append(queries[i], i) } // 按照 limit 从小到大排序,方便离线 sort.Slice(queries, func(i, j int)bool { return queries[i][2] < queries[j][2] })
ans := make([]bool, len(queries)) k := 0 for _, q := range queries { for ; k < len(edgeList) && edgeList[k][2] < q[2]; k++ { merge(edgeList[k][0], edgeList[k][1]) } ans[q[3]] = find(q[0]) == find(q[1]) } return ans }
复杂度分析
时间复杂度:O \big ( E \log E + m \log m + (E + m) \log n + n \big ),其中 E 是 edgeList 的长度,m 是 queries 的长度,n 是点数。对 edgeList 和 queries 进行排序分别需要 O(E\log E) 和 O(m\log m),并查集初始化需要 O(n),并查集查询和合并总共需要 O \big ((E+m)\log n \big )。
空间复杂度:O(\log E + m + n)。保存并查集需要 O(n) 的空间,保存 index 需要 O(m) 的空间,以及排序需要的栈空间。