并查集
利用并查集可以形成一棵树,用来表示连通如上图所示,具体的做法分为三个部分
首先是初始化数组
for(int i=1;i<=n;i++) num[i]=i;//初始化自己的祖先是自己
查找操作
int find(int x) {
int r=x;
while(num[r]!=r) r=num[r];//找当前元素的父亲节点,看它指向谁
//路径压缩,将上面找父亲节点途径的节点都直接指向最后的根节点,为以后的查询节省时间
int i=x,j;
while(i!=r) {
j=num[i];
num[i]=r;
i=j;
};
return r;
}
加入&合并
void join(int x,int y) {
int fx=find(x),fy=find(y);
if(fx!=fy) num[fx]=fy;
}
判断是否连通
int x,y,fx,fy;
fx=find(x);
fy=find(y);
if(fx==fy) //证明连通属于一个部落
else //说明属于不同的部落
挂一道经典题目
顺便附上题解
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#define Xiaobo main
using namespace std;
const int maxn=1e5+5;
const int mod=1e9+7;
int num[maxn*2];
int height[maxn];
int find(int x) {
int r=x;
while(x!=num[x]) {
x=num[x];
}
int j;
while(r!=x) {
j=num[r];
num[r]=x;
r=j;
}
return x;
}
void add(int x,int y) {
int fx=find(x);
int fy=find(y);
if(num[fx]!=fy) {
num[fx]=fy;
}
}
int Xiaobo()
{
int t;
cin>>t;
while(t--) {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n*2;i++) num[i]=i;
while(m--) {
char s;
getchar();
scanf("%c",&s);
int a,b;
scanf("%d%d",&a,&b);
if(s=='D') {
add(a,b+n);
add(a+n,b);
}
else if(s=='A') {
int fx=find(a);
int fy=find(b);
if(fx==fy) {
printf("In the same gang.\n");
}
else if(fx==find(b+n)) {
printf("In different gangs.\n");
}
else {
printf("Not sure yet.\n");
}
}
}
}
}