并查集

丶灬走出姿态 提交于 2020-02-17 05:36:44

并查集
并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。
(百度百科)
例题
小郑作为新生,刚刚来到美丽的比斯猪,学校规定每见到一个陌生人都要上去握手并成为好朋友,但为了避免把全校同学手都握了,学校还规定只要遇见一个陌生人,如果这个陌生人是他朋友认识的,那就是自己认识的,就不和她握手(朋友的朋友就是我的朋友,只要是能通过朋友关系串联起开,不管多远,都不握手)
这样问题就来了,因为学校里的同学实在太多了,如果要一个个问朋友认不认识这个人,再问朋友的朋友认不认识那个人。这样问下来一整天也不一定能够知道这个人自己到底认不认识。

int person[100];int find(int root)//查找认识的最远的人{int son = root; while(root != person[root])//先找出认识的最远的人(根节点)   root  = person[root];   while(son != root) {  int temp = person[son];//先用temp保存自己认识的人   person[son] = root;//让自己直接认识最远的人(根节点)   son = temp;//再让自己变成temp里原来认识的人  } return root;}bool shakeHand(int x,int y){ x = find(x);//查找x认识的最远的人 (根节点) y = find(y);//查找y认识的最远的人 (根节点) if(x!=y)//如果认识的人不相同,那么就握手 {  person[x] = y;//让x的根节点认识y的根节点  return true; } return false;  } int main(){ int n;//一共n个人 scanf("%d",&n); for(int i=1;i<=n;i++)  person[i] = i;//所有人都认识自己 int m;//一共m次握手  scanf("%d\n",&m); int total = 1;//每个人最多认识一个人  while(m--) {  int x,y;  scanf("%d %d",&x,&y);  if(shakeHand(x,y))//x和y握手成功   total++;  } if(total == n)  printf("所有人都互相认识了\n"); else  printf("还有人没有认识"); return 0;}
发布了1 篇原创文章 · 获赞 0 · 访问量 11
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!