用DFS求联通块
【分析】图也可以有dfs,bfs遍历。由于dfs更容易编写,一般用dfs找联通块:从每个'@'格子出发,递归遍历它周围的'@'格子每一次访问到一个就给它写上“联通分量编号”即下面的idx数组。这样就可以在访问之前知道是否已经被访问过,从而避免一个格子被访问多次。
#include<bits/stdc++.h>
using namespace std;
#define maxn 100+5
char pic[maxn][maxn];//存图
int m,n,idx[maxn][maxn];
void dfs(int r,int c,int id){
if(r<0||r>=m||c<0||c>=n)return ;//出界的格子
if(idx[r][c]>0||pic[r][c]!='@')return ;//不是'@'或已经被访问过
idx[r][c]=id;//将点记录下来
for(int dr=-1;dr<=1;dr++)
for(int dc=-1;dc<=1;dc++)
if(dr!=0||dc!=0)dfs(r+dr,c+dc,id);//向四个方向搜索·
}
int main()
{
while(scanf("%d%d",&m,&n)==2&&m&&n){
for(int i=0;i<m;i++)scanf("%s",pic[i]);
memset(idx,0,sizeof(idx));
int cnt=0;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)//每一次扫描所有为id的方格
if(idx[i][j]==0&&pic[i][j]=='@')dfs(i,j,++cnt);
printf("%d
",cnt);
}
return 0;
}
上面的代码用一个二重循环来找当前各子相邻的格子也可以用常量数组或8条dfs调用,可以根据自己喜好使用。这种算法还有个很好听的名字:种子填充(floodfill)
刘汝佳《算法竞赛入门经典(第二版)》P162