题目描述:
有A-K共11种不同的水管,每个水管的连通方向不同。给出一个M×N的田地水管图,求出最少需要多少个出水口可以灌溉全部田地。 原题 ZJU2412
分析:
粗略一看,此题可以用搜索算法来做。即寻找一共有多少个连通分量。
求图有多少连通分量,一个很高效的方法是用并查集。此题也可以用并查集来解决。
对于地图中每个格子,判断它的水管能否与其上面和左面的格子连通。若能,则并在一起。
最后统计并查集中有多少连通分支即可。
代码,0.00s
/*
ZJU2412 Farm Irrigation
*/
#include <stdio.h>
#define N 51
#define id(i,j) (i*m+j+1)
int dir[][2]={{-1,0},{0,-1}}; //up down
int link[][4]={ {1,0,1,0},{1,1,0,0} //A B
,{0,0,1,1},{0,1,0,1} //C D
,{1,0,0,1},{0,1,1,0} //E F
,{1,1,1,0},{1,0,1,1} //G H
,{0,1,1,1},{1,1,0,1} //I J
,{1,1,1,1}}; //K
int f[N*N],m,n;
char map[N][N],ch;
int x,y,u,v,p,q,t;
int connect(int u,int v,int e){
if(!e){ //up down
if(link[u][0]&&link[v][3]) return 1;
else return 0;
}
else{ //left right
if(link[u][2]&&link[v][1]) return 1;
else return 0;
}
}
int root(int p){
q=p;
while(f[q]) q=f[q];
while(f[p]){
t=f[p];
f[p]=q;
p=t;
}
return q;
}
void work(int i,int j,int e){
x=i+dir[e][0];
y=j+dir[e][1];
u=map[i][j];
v=map[x][y];
if(connect(u,v,e)){
p=root(id(i,j));
q=root(id(x,y));
if(p!=q) f[p]=q;
}
}
int main()
{
int i,j,k,ans;
while(scanf("%d%d",&n,&m),m!=-1||n!=-1)
{
//input
getchar();
for(i=0;i<n;i++){
for(j=0;j<m;j++){
scanf("%c",&ch);
map[i][j]=ch-'A';
}
getchar();
}
//init
for(i=0;i<=n*m;i++) f[i]=0;
//work
for(i=0;i<n;i++){
for(j=0;j<m;j++){
if(i) work(i,j,0); //up
if(j) work(i,j,1); //left
}
}
//count
ans=0;
for(i=0;i<n;i++)
for(j=0;j<m;j++){
k=id(i,j);
if(root(k)==k) ans++;
}
//output
printf("%d/n",ans);
}
return 0;
}