题目描述:
解析:
这个问题抽象为求一个图的连通子图的个数。可以采用DFS遍历,求出连通度;或者采用并查集。
此题使用使用并查集。
(1)初始化:将每个节点的父节点初始化为自己,此时n个节点有n个朋友圈;
(2)第一步:根据输入的序列,将node数组和对应的father数组进行第二波初始化,注意father[tail]=head,这样才能成功的从后往前寻找时停止;
(3)第三步:遍历。对于node中的每个节点,查找其父节点,如果此节点等于其父节点,即father[node]=node,说明已经找到祖先节点,则停止对该节点的查找,跳入下一个节点。反之说明还没有找到其祖先节点,那么使当前节点的父节点等于其父节点的父节点,然后再比较更新过后,这个节点的父节点跟父节点的父节点进行比较,直到相同。
(4)最后,整理为字典得到朋友圈个数。
知识点:
(1)enumerate()函数
——语法:enumerate(sequence, [start=0])
——参数:sequence是一个序列,迭代器或者其他迭代对象;start下标起始位置;
——返回值:返回enumerate枚举对象;
>>>seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1)) # 下标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
(2)并查集
了解并查集的思想和基本操作方式:即一直更新一个节点,第一次是它本身的父节点,第二次它的父节点变为它父节点的父节点,即爷节点。再比较它此时的父节点(也就是爷节点)是否跟爷节点(即太爷节点)相同,相同则break停止对该节点的寻找,不相同再更新其父节点为太爷节点。然后一直如此。
核心代码如下:
for node in nodes:
while True:
# 对于每个节点,找它的父节点,看他的父节点的父节点是谁,直到找到父节点跟节点相同,说明到头
father_of_node=father[node]
if father_of_node!=father[father_of_node]:
father[node]=father[father_of_node]
else:
break
代码:
n=int(input())
nodes=list(range(n))
father=list(range(n))
m=int(input())
edges=[]
for i in range(m):
edge=[int(i) for i in input().split(' ')]
edges.append(edge)
for edge in edges:
head=edge[0]
tail=edge[1]
father[tail]=head
for node in nodes:
while True:
# 对于每个节点,找它的父节点,看他的父节点的父节点是谁,直到找到父节点跟节点相同,说明到头
father_of_node=father[node]
if father_of_node!=father[father_of_node]:
father[node]=father[father_of_node]
else:
break
dic={}
for i,f in enumerate(father):
dic[f]=[]
print(len(dic))
延展知识:
此题还可以使用DFS遍历得到。
(1)原理:对于每个节点,对其执行一遍DFS后,会找到与之相连的所有节点,并将它标记。所以,执行了多少遍DFS,就有多少个连通子图;
(2)实现方法:刚开始每个节点都没走过。对于每个节点,判断其是否走过,即used[i]==1,没有则对齐实行DFS,同时k++,标记实行了几次DFS。对于每次DFS而言,其都通过不断调用自身,找到了与自己相连的所有节点。
基本代码如下:
n=int(input())
dis=[[0 for i in range(n)]for j in range(n)]
used=[0 for i in range(n)]
m=int(input())
for i in range(m):
a=[int(i) for i in input().split(' ')]
dis[a[0]][a[1]]=1
dis[a[1]][a[0]]=1
def DFS(i,n):
used[i]=1
for j in range(n):
if dis[i][j]==1:
if used[j]!=1:
DFS(j,n)
k=0
for i in range(n):
if used[i]==0:
k+=1
DFS(i,n)
print(k)