http://acm.hdu.edu.cn/showproblem.php?pid=1198水源的数目就是合并后的根的数目,并查集的合并就是对m*n个点的合并,合并有两种方式,水平和垂直。
这道题初始化有点多,通过观察图形,记录图的上下左右四个方位是否连通,然后得出他们彼此之间是否连通。
#include <iostream>
#include <string>
using namespace std;
struct T
{
bool right,left,down,up;
T()
{
right=left=down=up=false;
}
}s[11];
int parent[2502]; //考虑这m*n个点能构成多少个连通分量
bool link1[11][11]; //是否水平相连
bool link2[11][11]; //是否垂直相连
char map[51][51];
void init() //初始化这11张图片是否相连,包括水平、垂直两种方式
{
int i,j;
s[0].left=s[2].left=s[5].left=s[6].left=s[7].left=s[8].left=s[10].left=true;
s[1].right=s[3].right=s[5].right=s[6].right=s[8].right=s[9].right=s[10].right=true;
s[0].up=s[1].up=s[4].up=s[6].up=s[7].up=s[9].up=s[10].up=true;
s[2].down=s[3].down=s[4].down=s[7].down=s[8].down=s[9].down=s[10].down=true;
for(i=0;i<11;i++)
for(j=0;j<11;j++)
{
link1[i][j]=s[i].right && s[j].left;
link2[i][j]=s[i].down && s[j].up;
}
}
int UFfind(int i)
{
int j,temp;
for(j=i;parent[i]>=0;i=parent[i]);
while(j!=i)
{
temp=parent[j];
parent[j]=i;
j=temp;
}
return i;
}
void UFunion(int i,int j)
{
int temp;
i=UFfind(i);
j=UFfind(j);
if(i==j)
return;
temp=parent[i]+parent[j];
if(parent[i]<=parent[j])
{
parent[i]=temp;
parent[j]=i;
}
else
{
parent[j]=temp;
parent[i]=j;
}
}
int main()
{
int i,j,m,n,pi,pj,res;
init();
while(cin>>m>>n,(m+n)!=-2)
{
memset(parent,-1,sizeof(parent));
res=0;
for(i=0;i<m;i++)
cin>>map[i];
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
if(j<n-1 && link1[map[i][j]-'A'][map[i][j+1]-'A'])
{
pi=i*n+j;
pj=i*n+j+1;
UFunion(pi,pj);
}
if(i<m-1 && link2[map[i][j]-'A'][map[i+1][j]-'A'])
{
pi=i*n+j;
pj=(i+1)*n+j;
UFunion(pi,pj);
}
}
for(i=0;i<m;i++) //搜索根的数目
for(j=0;j<n;j++)
if(parent[i*n+j]<0)
res++;
cout<<res<<endl;
}
return 0;
}
posted on 2011-09-15 12:38
大大木马 阅读(316)
评论(0) 编辑 收藏 引用