杭电1198 并查集

本题不同于其他的并查集,看似很难,其实只要读懂题目,思路清晰,就很容易写出来,题目所示的田看似要用二维数组,但是我用一维数组也可以解决,先输入字符串,根据字符串匹配到是11种田中的哪一种,然后根据田的不同用一个二维数组表示不同的田,然后利用并查集,有水管相接的集合在一起;

代码如下:


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 
       
#include
#include
#include
int father[3000],Rank[3000],i,b[3000];
int bo[11][4]= {{1,1,0,0},{1,0,1,0},{0,1,0,1},{0,0,1,1},{1,0,0,1},{0,1,1,0},{1,1,1,0},{1,1,0,1},{0,1,1,1},{1,0,1,1},{1,1,1,1}};
//11种田,以上、左、右、下的顺序和1、0表示其上 、左、右、下有没有水管;
int find_set(int x)
{
if(x!=father[x])
father[x]=find_set(father[x]);
return father[x];
}
void Union(int x,int y)
{
x=find_set(x);
y=find_set(y);
if(x==y)
return;
if(Rank[x]>Rank[y])
father[y]=x;
else
{
if(Rank[y]==Rank[x])
Rank[y]++;
father[x]=y;
}
}
int main()
{
int n,m,i,j,x,y,z;
char a[60][60];
while(1)
{
int sum=0,flag=0;
for(i=0;i<3000;i++)
{
b[i]=i;
father[i]=i;
Rank[i]=0;
}
scanf("%d%d",&m,&n);
if(m==-1&&n==-1) break;
getchar();
for(i=0; i
{
for(j=0; j
{
scanf("%c",&a[i][j]); //利用二维数组输入
}
getchar();
}
for(i=0; i
{
for(j=0; j
{
if(i==0&&j>0)
{
x=a[i][j]-'A'; //匹配到田,例如如果a[i][j]=D,x=3;
y=a[i][j-1]-'A';
if(bo[x][1]+bo[y][2]==2) //根据匹配到的田看如果有水管相接则合并集合
{
flag=flag+1;
Union(b[j],b[j-1]); //这里的数组b[]表示所有的田,注意是一维数组,而不是二维数组
}
}
if(i>0&&j==0)
{
x=a[i][j]-'A';
y=a[i-1][j]-'A';
if(bo[x][0]+bo[y][3]==2)
{
Union(b[i*n],b[(i-1)*n]);flag=flag+1;
}
}
if(i>0&&j>0)
{
x=a[i][j]-'A';
y=a[i][j-1]-'A';
z=a[i-1][j]-'A';
if(bo[x][1]+bo[y][2]==2)
{
Union(b[i*n+j],b[i*n+j-1]);flag=flag+1;
}
if(bo[x][0]+bo[z][3]==2)
{
Union(b[i*n+j],b[i*n+j-n]);flag=flag+1;
}
}
}
}
for(i=0;i
{
if(father[i]==i)
sum=sum+1;
}
printf("%d\n",sum);
}
return 0;
}

你可能感兴趣的:(ACM)