裸的并查集使用,注意数组的大小一遍A过.
#include <iostream>
#include<stdio.h>
#include<list>
using namespace std;
const int maxn = 1000000 + 5;
int fa[maxn];
//还需要考虑是否是南北或者东西方向
//另外还需要考虑边界条件
void Init()
{
for(int i = 0;i < maxn;i++){
fa[i] = i;
}
}
int finf(int i)
{
int t = i;
while(fa[i] != i){
i = fa[i];
}//找到根i;
while(fa[t] != t){
t = fa[t];
fa[t] = i;
} //压缩路径,将所有的节点连到根上
return i;
}
bool same(int a,int b)
{
return finf(a) == finf(b);
}
int Union(int a,int b)
{
int f1 = finf(a);
int f2 = finf(b);
if(f1 <= f2){
fa[f2] = f1;
}
else fa[f1] = f2;
}
bool Yes(int a,int b,int c)
{
if(a + c == b || a - c == b || a + 1 == b||a - 1 == b)return true;
else return false;
}
int main()
{
int r,c,n,ans = 0;
scanf("%d%d",&r,&c);
scanf("%d",&n);
Init();
for(int i = 0;i < n;i++){
int a,b;
scanf("%d%d",&a,&b);
a--;
b--;
if(Yes(a,b,c))
if(!same(a,b))Union(a,b);
}
/* for(int i = 0;i < c * r;i++){
printf("%d ",fa[i]);
}
printf("\n");*/
for(int i = 0;i < c * r;i++){
if(fa[i] == i)ans++;
}
printf("%d\n",ans);
return 0;
}