合根植物(蓝桥杯)–并查集的运用
w星球的一个种植园,被分成 m * n 个小格子(东西方向m行,南北方向n列)。每个格子里种了一株合根植物。
这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。
如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?
思路:有n行m列,即共有n*m个植物,他们两两之间可能会有联系,在这里做一个约定,就是右边的追随左边的为boss,当然开始的时候每一个人的boss都是自己,这样到最后只需要观察有多少个boss,就知道有多少株合根植物了。
注:记住“擒贼先擒王”的原则,就是一团的一个人追随了另一个团,那么他们的王就要追随人家。和“压缩路径”,就是帮助找到自己boss的要受到提拔,直接追随总boss。
代码如下:
#include <iostream>
#define maxn 1000000
using namespace std;
int n,m,f[maxn];
void init()
{
int i;
for(i=1;i<=n;i++)
{
f[i]=i;
}
}
int getf(int x)
{
if(f[x]==x)
{
return x;
}
else {
f[x]=getf(f[x]);
return f[x];
}
}
void merge(int v,int u)
{
int t1,t2;
t1=getf(v);//分别寻找两者的boss
t2=getf(u);
if(t1!=t2)
{
f[t2]=t1;//两者的boss不是同一个,这里遵循“向左原则”,右边追随左边
}
}
int main()
{
int i,x,y,sum=0;
cin>>x>>y;
n=x*y;
cin>>m;
init();//初始化,将n个单独的个体分别设置其追随的boss是自己
for(i=1;i<=m;i++)
{
cin>>x>>y;
merge(x,y);//合并两者
}
for(i=1;i<=n;i++)
{
if(f[i]==i)
{
sum++;
}
}
cout<<endl;
return 0;
}