题意

平面上有若干个点,从每个点出发,你可以往东南西北任意方向走,直到碰到另一个点,然后才可以改变方向。
请问至少需要加多少个点,使得点对之间互相可以到达。

题解

如果n个点之间可以相互到达,则将n个点放入一个集合。所需添加的点数就是集合数-1
故:可以遍历所有点对,若彼此可达,则使用并查集将二者并到一起。
最后查询祖先为自身的点数,即树根数集合数。

Code

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
int fa[maxn];                   //记录祖先节点
vector<pair<int,int>> a ;
int fi(int x){                  //find函数寻找祖先
    return x == fa[x] ? x : fa[x] = fi(fa[x]);
}

void un(int x,int y){           //union函数建立两点关系
    int p = fi(x);
    int q = fi(y);
    if(p != q) fa[p] = q;
}

int main()
{
    int n,m;
    cin>>n;
    a.resize(n);
    for(int i = 1;i <= n;++i) fa[i] = i;        //init
    for(int i = 1;i <= n;++i){
        scanf("%d%d",&a[i].first,&a[i].second);
    }
    for(int i = 1;i <= n;++i){
        for(int j = i + 1;j <= n;++j){
            if(a[i].first == a[j].first || a[i].second == a[j].second){
                un(i,j);
            }
        }
    }
    int cnt =0 ;
    for(int i = 1;i <= n;++i){
        if(fa[i] == i){
            cnt++;
        }
    }
    printf("%d\n",cnt-1);

    return 0;
}