题目
思路
即给一个无向图,判断两个结点是否连通。
并查集
路径优化的内容上面讲了,对于另一个优化:按秩合并:
在合并两个子树的时候,分别设两个子树的结点个数为tot[i],tot[j]。若tot[i]>tot[j],那么理想的方法是把j子树接到i子树上,原因是,这样做只会有tot[j]个结点的深度加一,而另外一种接法需要有tot[i]个结点的深度加一。当然更多的结点深度越小越好。
代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#define _for(i,a,b) for(int i = a; i<b; i++)
#define _rep(i,a,b) for(int i = a; i<=b; i++)
using namespace std;
const int maxn = 5000+10;
int n, m, p, fa[maxn], tot[maxn];
int getfa(int x){
if (fa[x] == x) return x;
fa[x] = getfa(fa[x]); // 路径压缩
return fa[x];
}
int hebing(int x, int y){
x = getfa(x);
y = getfa(y);
if (tot[x] > tot[y]) swap(x,y);
fa[x] = y;
tot[x] += tot[y];
}
int main(){
scanf("%d%d%d",&n,&m,&p);
_rep(i,1,n){
fa[i] = i;
tot[i] = 1;
}
int u,v;
_for(i,0,m){
scanf("%d%d",&u,&v);
hebing(u,v);
}
_for(i,0,p){
scanf("%d%d",&u,&v);
if (getfa(u) == getfa(v)) printf("Yes\n");
else printf("No\n");
}
return 0;
}