并查集(集并查)
来源:互联网 发布:htc m8 刷Windows教程 编辑:程序博客网 时间:2024/06/09 17:37
并查集其实应该是“集并查”——集合的并和查
——强哥
外国老师讲课怕学生听不懂显得自己不专业,中国某些老师教课怕学生听懂了,显得自己不专业。所以老外讲课通俗易懂,某些老师讲课全是专业名词,弄得学生一头雾水。
——改自网易云课堂一网友评论
网友的这句话从并查集的翻译上确实可见一斑呀!
Description
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。 规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。
Input
第一行:三个整数n,m,p,(n< =5000,m< =5000,p< =5000),分别表示有n个人,m个亲戚关系,询问p对亲戚关系。 以下m行:每行两个数Mi,Mj,1< =Mi,Mj< =N,表示Mi和Mj具有亲戚关系。 接下来p行:每行两个数Pi,Pj,询问Pi和Pj是否具有亲戚关系。
Output
P行,每行一个’Yes’或’No’。表示第i个询问的答案为“具有”或“不具有”亲戚关系。
测试样例:
(2,4) {2,4}
(5,7) {2,4} {5,7}
(1,3) {1,3} {2,4} {5,7}
(8,9) {1,3} {2,4} {5,7} {8,9}
(1,2) {1,2,3,4} {5,7} {8,9}
(5,6) {1,2,3,4} {5,6,7} {8,9}
(2,3) {1,2,3,4} {5,6,7} {8,9}
#include<iostream>using namespace std;int pre[50002],n,m,p,a,b;int find(int x){//找祖先,为了方便后面压缩路径,用循环不用递归 int i=x; while(pre[i]!=i) i=pre[i]; int j=x,t; while(pre[j]!=i){ t=pre[j]; pre[j]=i; j=t; } return i;}void join(int a,int b){//将互为亲戚的两个元素放到一个集合,即祖先相同 a=find(a); b=find(b); if(a!=b) pre[a]=pre[b];}int main(){ cin >> n >> m >> p; int i; for(i=1;i<=n;i++)//注意,初始化很容易忘掉 pre[i]=i; for(i=1;i<=m;i++){ cin >> a >> b; join(a,b); } for(i=1;i<=p;i++){ cin >> a >> b; if(find(a)==find(b)) cout << "Yes" <<endl; else cout << "No" << endl; } return 0;}
上一道例题:)
7-7 朋友圈(25 分)
某学校有N个学生,形成M个俱乐部。每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出,如果A和B是朋友,且B和C是朋友,则A和C也是朋友。请编写程序计算最大朋友圈中有多少人。
输入格式:
输入的第一行包含两个正整数N(≤30000)和M(≤1000),分别代表学校的学生总数和俱乐部的个数。后面的M行每行按以下格式给出1个俱乐部的信息,其中学生从1~N编号:
第i个俱乐部的人数Mi(空格)学生1(空格)学生2 … 学生Mi
输出格式:
输出给出一个整数,表示在最大朋友圈中有多少人。
输入样例:
7 4
3 1 2 3
2 1 4
3 5 6 7
1 6
输出样例:
4
思路:
这道题是第一次实验室训练赛做的,当时忘了并查集的思路,看了这篇博客才想起来。当时看到这个题,马上就想到了要用能压缩路径的并查集,直接用并查集肯定是通不过的,但我学到的并查集的这个压缩路径写的很不好,他是当作副产品加进来的,在找祖先的时候顺便压缩路径,所以会遗漏部分元素(具体哪部分我也没有验证),这些元素的祖先并不是最大的(即这些元素的祖先还有祖先)。这个是我刚接触并查集的时候思考过的问题,所以印象比较深刻,当时找到了解决办法,就是最后把所有的元素的祖先都找一遍。
感想:
还记得暑假时,那个炎热的下午,上完集训队的课,和儿子一起爬回浮山公寓,然后牺牲了午睡时间就开始搞了半下午的并查集,多亏了当时的思考,比赛时才能游刃有余。以后遇到问题还是多思考!
#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<cmath>using namespace std;int pre[30001];int find(int x){ int i=x; while(pre[i]!=i) i=pre[i]; int j=x,t; while(pre[j]!=i){ t=pre[j]; pre[j]=i; j=t; } return i;}void join(int a,int b){ a=find(a); b=find(b); if(a!=b) pre[a]=pre[b];}int main(){ int book[30001]={}; int n,m; int max=0; cin >> n >> m; for(int i=1;i<=n;i++){ pre[i]=i; } for(int i=0;i<m;i++){ int q; cin >> q; int x,y; cin >> x; for(int j=1;j<q;j++){ cin >> y; join(x,y); } } for(int i=1;i<=n;i++) find(i); for(int i=1;i<=n;i++){ book[pre[i]]++; if(book[pre[i]]>max) max=book[pre[i]]; } cout << max; return 0;}
- 并查集(集并查)
- HDU3938 并查集 并查集
- 并查集(含关系并查集)
- 【并查集】食物链(关系并查集)
- 【并查集】并查集详解(转)
- 分组并查集(种类并查集)
- 并查集, 畅通工程(简单并查集)
- [数据结构]并查集水体POJ2236(并查集)
- HDU1232 并查集<并>
- 并查集(disjoint_set)
- 并查集(模板)
- 并查集(亲戚)
- POJ2524(并查集)
- POJ_2236(并查集)
- poj2492(并查集)
- HDU1272(并查集)
- 随笔(并查集)
- POJ1988(并查集)
- 【Hadoop】Yarn 框架原理及运作机制
- MyBatis传入参数的问题
- Luogu P2719 搞笑世界杯
- Java 正则学习笔记
- 设计模式之单例模式
- 并查集(集并查)
- ftp上传下载记录
- Java基础详解 (一)Java的类成员访问权限修饰词(以及类访问权限)
- linux下安装redis
- JAX-WS创建我的第一个webService
- python脚本中的#!/usr/bin/python
- 宏函数和函数的区别及优缺点
- 使用mybatis查询sql注入到 map 中,唯空字段 也获取出来
- React Developer Tools