问题描述 给定一个正整数n,有n个人,编号分别为0,1,2...n-1,刚开始每个人独立一只队伍。现在进行m次合并操作,把x和y所在的两只队伍合并。 现在想知道任意两人个人x和y是否在同一只队伍。 输入 输入第一行是一个正整数n(n<=100000). 第二行是一个正整数m(m<=100000)。 接下来m行每行两个正整数x和y(0<x,y<n),表示把x和y所在的队伍合并。 再接下来是一个正整数k,表示有k个查询。 最后k行每行两个正整数a和b(0<a,b<n),表示需要查询a和b是否在同一只队伍。 输出 输出总共k行,每个查询输出一行,如果a和b在同一只队伍输出yes,否则输出no。
时间: 2024-03-17 08:47:05 浏览: 138
判断输入的任何一个正整数n,是否等于某个连续正整数序列之和。
3星 · 编辑精心推荐
解题思路:
本题可以使用并查集来解决。并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
具体来说,我们可以把每个人看做一个节点,每个队伍看做一棵树。刚开始时,每个节点都是一棵只包含自己的树。每次合并时,我们就把两个节点所在的树合并成一棵树。
为了方便合并,我们可以使用一个数组 parent 来记录每个节点的父节点。刚开始时,每个节点的父节点都是自己。当两个节点所在的树合并时,我们就把其中一个节点的父节点指向另一个节点的父节点,这样两个节点就位于同一棵树上了。
查询时,我们只需要判断两个节点的根节点是否相同即可。如果相同,说明它们在同一棵树上;否则,它们不在同一棵树上。
代码实现:
```python
def find(x, parent):
if parent[x] != x:
parent[x] = find(parent[x], parent)
return parent[x]
n = int(input())
m = int(input())
parent = list(range(n))
for i in range(m):
x, y = map(int, input().split())
px, py = find(x, parent), find(y, parent)
if px != py:
parent[px] = py
k = int(input())
for i in range(k):
a, b = map(int, input().split())
if find(a, parent) == find(b, parent):
print("yes")
else:
print("no")
```
时间复杂度分析:
对于每个查询,我们需要找到两个节点的根节点。由于每次查找时都会把路径上的所有节点的父节点更新为根节点,因此,每个节点的父节点最多只会被更新一次。
因此,总时间复杂度为 $O(m+n\log n+k\log n)$,其中 $m$ 是合并操作的次数,$n$ 是节点数,$k$ 是查询的次数。
阅读全文