任意点-并查集
题目描述
平面上有若干个点,从每个点出发,你可以往东南西北任意方向走,直到碰到另一个点,然后才可以改变方向。 请问至少需要加多少个点,使得点对之间互相可以到达。
输入描述:
第一行一个整数n表示点数( 1 <= n <= 100)。 第二行n行,每行两个整数xi, yi表示坐标( 1 <= xi, yi <= 1000)。 y轴正方向为北,x轴正方形为东。
输出描述:
输出一个整数表示最少需要加的点的数目。
分析:
知识点:并查集。n个点,横坐标相同或者纵坐标相同则说明可以互相抵达,则这两个点可以连成一条路径,用遍历连完点后,得到 i 条完整的路径(单独一个点也是一条路径),则需要增加i-1个点。
例如上图,连完所有点后就得到了4条路径那么需要增加3个点
AC代码:
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int n,x[1005],y[1005],fa[1005];
void init(){ //初始化源头
for(int i=0;i<n;++i)
fa[i]=i;
}
int find(int i){ //找源头
if(fa[i]==i)
return i;
else{
fa[i]=find(fa[i]); //压缩路径
return fa[i];
}
}
void union_z(int i,int j){ //联合两点
int fa_i=find(i);
int fa_j=find(j);
fa[fa_i]=fa_j;
}
int main(){
cin>>n;
for(int i=0;i<n;++i)
scanf("%d %d",&x[i],&y[i]);
init();
for(int i=0;i<n-1;++i)
for(int j=i+1;j<n;++j)
if(x[i]==x[j]||y[i]==y[j])
union_z(i,j);
for(int i=0;i<n;++i)
find(i); //再压缩一次路径(感觉还可以优化一下但是懒得想了)
sort(fa,fa+n);
int flag=fa[0],count=0;
for(int i=1;i<n;++i) //计算联合过后有几条路径
if(fa[i]!=flag){
flag=fa[i];
count++;
}
printf("%d",count);
}