找关系,本人倾向于运用递归实现。
并查集
Description
并查集的一个常用场合是:快速判断两个元素是否在同一个集合。
并查集的原理与实现请参考Article里面的文章。
Input
测试用例的第一行是一个整数 n ( 0 < n < 100000 ) ,表示一共有多少个元素。每个元素定义为非负整数,范围是 0 ~ n-1
接下来是一个正整数m ( 0 < m < n*(n-1) ),表示有m个关系。
接下来有m行,每行是两个非负整数a和b,表示a和b之间有关系(即在同一个集合)。
接下来是一个正整数t,表示有t个问题。
接下来有t行,每行是两个非负整数x和y,表示提问x和y是否在同一个集合。
Output
对应输入的t个问题的次序输出t行结果,如果x和y是在同一个集合中,则输出y,否则n 。
Sample Input
5
3
0 3
2 1
4 2
3
0 4
1 4
1 3
Sample Output
n
y
n
Hint
在 "每行两个非负整数a和b,表示a和b之间有关系(即在同一个集合)"中,可能存在重复的关系,如:
1 5
5 1
Author
#include<bits/stdc++.h> using namespace std; int n,m,t; int fa[100006]; void init() { for(int i=0;i<n;i++) fa[i]=i; } int find_fa(int a) { return fa[a]==a?a:find_fa(fa[a]); } int main() { int ui,uc; while( ~scanf("%d",&n)){ init(); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d",&ui,&uc); int jk,kl; jk=find_fa(ui),kl=find_fa(uc); if(jk!=kl) fa[jk]=kl; ///关键 } scanf("%d",&t); while(t--){ scanf("%d%d",&ui,&uc); int jk,kl; jk=find_fa(ui),kl=find_fa(uc); if(jk!=kl) printf("n "); else printf("y "); } } return 0; }
下面代码有压缩(虽然压缩不完整qwq).
#include<bits/stdc++.h> using namespace std; int n,m,t; int fa[100006]; void init() { for(int i=0;i<n;i++) fa[i]=i; } int find_fa(int a) { return fa[a]==a?a:find_fa(fa[a]); } int main() { int ui,uc; while( ~scanf("%d",&n)){ init(); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d",&ui,&uc); int jk,kl; jk=find_fa(ui),kl=find_fa(uc); if(jk!=kl){ /// 此处压缩,对比前面的代码。但是该压缩不太完整,不能实行到最短。 if(jk<kl) fa[kl]=jk; else fa[jk]=kl; } else{ fa[ui]=fa[uc]=jk; } } scanf("%d",&t); while(t--){ scanf("%d%d",&ui,&uc); int jk,kl; jk=find_fa(ui),kl=find_fa(uc); if(jk!=kl) printf("n "); else printf("y "); } } return 0; }