HDU 1198 Farm Irrigation 【并查集】

 思路:

         此题就是基本的并查集的应用。

 关于此题的一些处理技巧:

(1)如何把A->k块表示出来,从而使之容易判断两块地是否可以归并到一起

例如:


把A块划分如上图所示,有4个方向,与其他块有通路的方向标记为1,反之为0,所以A={1 1 0 0},其他同理

  (2)如何在map中识别是那一块,然后根据这一块找到它的四个方向的0/1情况呢?这里把A->K等效成了0-11(通过坐标找到map所在位置的字符,然后用此字符减去'A'),然后开辟一个a[11][4]的数组标记A->K每一块的方

 (3)约定把map中的块从左到右,从上到下,标记为第1块,一直到n*m块,通过坐标(i,j),可以计算这是那一块(公式(i-1)*n+j),从而在下面的并查集的函数(初始化函数,find函数,以及归并函数)中容易操作

    AC代码:

 

#include<stdio.h>
int father[2505],r[2505];
int map[55][55];
int m,n;
int a[11][4]={{1,1,0,0},{1,0,0,1},{0,1,1,0},{0,0,1,1},{1,0,1,0},{0,1,0,1},{1,1,0,1},{1,1,1,0},{0,1,1,1},{1,0,1,1},{1,1,1,1}};
int count;
void initial()
{
     int i;
	 for(i=1;i<=m*n;i++)
	 {
	     father[i]=i;
		 r[i]=1;
	 }
}
int find(int x)
{
     if(father[x]!=x)
		 father[x]=find(father[x]);
	 return father[x];
}
void Union(int a,int b)
{
     int x=find(a);
	 int y=find(b);
     if(x==y)return ;
	 if(r[x]<=r[y])
	 {
	       father[x]=y;
		   r[y]+=r[x];
		   count--;
	 }
	 else
	 {
	       father[y]=x;
		   r[x]+=r[y];
		   count--;
	 }
}
int main()
{
	int i,j;
	char x;
	while(scanf("%d%d",&m,&n)!=-1&&m>=0&&n>=0)
	{
	 getchar();
	 for(i=1;i<=m;i++)
	 {
		 for(j=1;j<=n;j++)
		 {
		     scanf("%c",&x);
			 map[i][j]=x-'A';
		 }
		 getchar();
	 }
	 count=n*m;
	 initial();
	 for(i=1;i<=m;i++)
		 for(j=1;j<=n;j++)
		 {
		     if(i-1>0)
			 {
			     if(a[map[i][j]][0]==1&&a[map[i-1][j]][2]==1)
					 Union((i-1)*n+j,(i-2)*n+j);
			 }
			 if(j-1>0)
			 {
			     if(a[map[i][j]][1]==1&&a[map[i][j-1]][3]==1)
					 Union((i-1)*n+j,(i-1)*n+(j-1));
			 }
		 }
      printf("%d\n",count);
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值