赞
踩
某国王要给n个岛之间修桥,桥是双向的,国王可以将a岛和b岛连接起来,也可以将两座岛的桥炸掉,国王想知道经过一系列操作之后两座岛之间是否连接。
输入:岛屿数量n,每行第一个数是选择,1 是 合并,然后再输入两个岛屿a和b,输入 2 是炸掉最近一次合并的桥,如果没有桥就不需要任何操作,后面不需要岛屿a和b,如果输入 3 进行查询a与b是否相连。输入不是1,2,3则结束。
输出:两座岛是否连接,“ Yes ” or “ No ”。
5
1 2 3
1 3 4
2
3 3 4
1 2 5
3 3 5
4
No
Yes
可撤销并查集可以做,但是为了简便直接利用python的特性(可以直接将每个合并操作之后的父数组保存)
用一个数组 st 记录父类数组 f 的值,每一次合并操作就将新的父类数组添加到st中,然后是 2 删除操作就将st最后一个删除,然后将新的最后一个值赋值给父类 f,然后其他就用并查集板子就行了。
st.append(f.copy())
为什么在添加f的时候用了一个 copy() 操作:
st 列表中的所有元素都是对 f 列表的引用。因为 f 列表在每次修改后,其引用仍然指向同一个内存位置,所以 st 列表中的所有引用都会指向更新后的 f 列表。
所以每次 f 被修改时,st 中所有之前的数组也会跟着变化。
为了避免这种情况,在每次修改 f 后,将 f 的一个副本添加到 st 中,而不是直接添加 f。
n = int(input()) f = [0] + [i for i in range(1, n + 1)] st=[f.copy()] def find(a): if f[a] == a: return a f[a] = find(f[a]) return f[a] def unit(a, b): x = find(a) y = find(b) f[x] = y f = [0] + [i for i in range(1, n + 1)] while True: s=input() o=int(s[0]) if o == 1: a=int(s[2]);b=int(s[4]) unit(a, b) st.append(f.copy()) elif o == 2: if len(st)>1: st.pop() f=st[-1] elif o == 3: a = int(s[2]) b = int(s[4]) x = find(a) y = find(b) if x == y: print('Yes') else: print('No') else: break
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。