0
点赞
收藏
分享

微信扫一扫

【并查集】合根植物(连通块的数数量)


w 星球的一个种植园,被分成 m*n 个小格子(东西方向 m 行,南北方向 n 列)。每个格子里种了一株合根植物。

这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。

如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?

5 4
16
2 3
1 5
5 9
4 8
7 8
9 10
10 11
11 12
10 14
12 16
14 18
17 18
15 19
19 20
9 13
13 17

【并查集】合根植物(连通块的数数量)_算法

答案:5

当两个格子出现连根现象时,合并两个格子代表的集合,最后求根节点的个数,即为连通块的个数。

模板:初始化,查找根节点,合并两个节点代表的集合

初始化:每个节点各自为树。

【并查集】合根植物(连通块的数数量)_初始化_02

 

void init(){
  for(i:1~n)dp[i]=i;
}

查找根节点:递归压缩路径

【并查集】合根植物(连通块的数数量)_ci_03

 

int find(int x){
  if(p[x]!=x){
     p[x]=find(p[x]);
  }
  return p[x];
}

 合并两个节点代表的集合:

【并查集】合根植物(连通块的数数量)_ci_04

 

void join(int x,int y){
  if(find(x)!=find(y)){
     p[find(x)]=find(y);
  }
}

代码:

#include <iostream>
using namespace std;
const int N=1000001;
int n;
int p[N];
void init(){
  for(int i=1;i<=n;i++){
    p[i]=i;
  }
}
int find(int x){
   if(p[x]!=x)p[x]=find(p[x]);
   return p[x];
}
void join(int x,int y){
  if(find(x)!=find(y)){
    p[find(x)]=find(y);
  }
}
int a,b,k;
int main()
{
  cin>>a>>b;
  n=a*b;
  init();
  cin>>k;
  for(int i=0;i<k;i++){
    int x,y;
    cin>>x>>y;
    join(x,y);
  }
  int ans=0;
  for(int i=1;i<=n;i++){
    if(p[i]==i)ans++;
  }

  cout<<ans;

  return 0;
}

举报

相关推荐

0 条评论