1346:【例4-7】亲戚(relation)
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 19158 通过数: 3148
【题目描述】
或许你并不知道,你的某个朋友是你的亲戚。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。如果能得到完整的家谱,判断两个人是否是亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。在这种情况下,最好的帮手就是计算机。为了将问题简化,你将得到一些亲戚关系的信息,如Marry和Tom是亲戚,Tom和Ben是亲戚,等等。从这些信息中,你可以推出Marry和Ben是亲戚。请写一个程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。
【输入】
输入由两部分组成。
第一部分以N,M开始。N为问题涉及的人的个数(1≤N≤20000)。这些人的编号为1,2,3,…, N。下面有M行(1≤M≤1000000),每行有两个数ai,biai,bi,表示已知aiai和bibi是亲戚。
第二部分以Q开始。以下Q行有Q个询问(1≤ Q ≤1000000),每行为ci,dici,di,表示询问cici和didi是否为亲戚。
【输出】
对于每个询问ci,dici,di,输出一行:若cici和didi为亲戚,则输出“Yes”,否则输出“No”。
【输入样例】
10 7 2 4 5 7 1 3 8 9 1 2 5 6 2 3 3 3 4 7 10 8 9
【输出样例】
Yes No Yes
这道题可以用并查集来做,但在并查集的基础上还分了好几个档次
①四十分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,m,ki,kj; 4 int sum[20005],q; 5 void csh(){ 6 for(int i=1;i<=m;i++){ 7 sum[i]=i; 8 } 9 } 10 int find(int a){ 11 if(sum[a]==a)return a; 12 return find(sum[a]); 13 } 14 int main(){ 15 cin>>m>>n; 16 csh(); 17 for(int i=1;i<=n;i++){ 18 cin>>ki>>kj; 19 if(find(ki)!=find(kj)){ 20 sum[find(kj)]=find(ki); 21 } 22 } 23 cin>>q; 24 while(q--){ 25 cin>>ki>>kj; 26 if(find(ki)==find(kj))cout<<"Yes"<<endl; 27 else cout<<"No"<<endl; 28 } 29 return 0; 30 }
四十分代码是只在并查集算法的基础上解题,没有任何优化
②九十分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,m,ki,kj; 4 int sum[20005],q; 5 void csh(){ 6 for(int i=1;i<=m;i++){ 7 sum[i]=i; 8 } 9 } 10 int find(int a){ 11 if(sum[a]==a)return a; 12 find(sum[a]); 13 } 14 void hb(int a,int b){ 15 sum[find(a)]=find(b); 16 } 17 int main(){ 18 scanf("%d%d",&m,&n); 19 csh(); 20 for(int i=1;i<=n;i++){ 21 scanf("%d%d",&ki,&kj); 22 hb(ki,kj); 23 } 24 scanf("%d",&q); 25 while(q--){ 26 scanf("%d%d",&ki,&kj); 27 if(find(ki)==find(kj))printf("Yes "); 28 else printf("No "); 29 } 30 return 0; 31 }
由于printf和scanf的输入输出速度要大于cin和cout的速度,所以我们可以选择在并查集的基础上把cin,cout改成printf和scanf
由测试结果我们可以看到,唯一超时了一个点也仅仅超了1ms,离成功很近了;
我们要知道一个知识:一般情况下,V(cin,cout)<V(printf,scanf)<V(手写快读)
手写快读就是先读入一个字符串,再把它们变成数字,虽然麻烦,但是快啊
所以我们可以选择把printf和scanf再换成手写快读
③满分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,m; 4 int ki,kj; 5 int sum[20005],q; 6 void csh(){ 7 for(int i=1;i<=m;i++){ 8 sum[i]=i; 9 } 10 } 11 int find(int a){ 12 if(sum[a]==a)return a; 13 return find(sum[a]); 14 } 15 void hb(int a,int b){ 16 sum[find(a)]=find(b); 17 } 18 int kd(){//快读函数 19 int res=0,flag=0; 20 char ch; 21 if((ch=getchar())=='-')flag=1;//判断是否为负数 22 else if(ch>='0'&&ch<='9')res=ch-'0'; 23 while((ch=getchar())>='0'&&ch<='9'){ 24 res=res*10+ch-'0'; 25 } 26 return flag?-res:res; 27 } 28 int main(){ 29 m=kd(); 30 n=kd(); 31 csh(); 32 for(int i=1;i<=n;i++){ 33 ki=kd(); 34 kj=kd(); 35 hb(ki,kj); 36 } 37 q=kd(); 38 while(q--){ 39 ki=kd(); 40 kj=kd(); 41 if(find(ki)==find(kj))printf("Yes "); 42 else printf("No "); 43 } 44 return 0; 45 }