【转自己的落谷博客】联通块的dfs

最近做了三道题,几乎用了同样的代码。
他们都是地图中的联通问题。
分别是P1596 [USACO10OCT]Lake Counting S,
CF598D Igor In the Museum,
P1141 01迷宫,
其要求都是在一个图中,寻找特定要求的连通块。
统计连通块的数目(P1596)或者每个连通块内的坐标数量(P1141)
或者连通块所接壤的非连通坐标的数目和(CF598D)。

其中图的规模均为n^2(1e6),查询的规模也是如此,
因此每次在查询时搜索并不是个省时间的好主意,所以三道题我都用了预处理,
用f[i][j]来确定每个点所拥有的数值,其中f[i][j]的含义并不相同,
但均可以在同一步骤中出现。
基本的实现方法都是dfs
用的大同小异;
分别展示dfs的部分

 


 

int o[1010][1010];//是否走过 
char s[1010][1010];//坐标上的点是什么 
int n,m,u;
int z[8]={-1,1,0,0,1,-1,-1,1},w[8]={0,0,-1,1,1,-1,1,-1};
void search(int x,int y)
{
if(x==0||y==0||x>n||y>m)
{
return;
}
for(int i=0;i<8;i++)
{    
if(s[x+z[i]][y+w[i]]=='W'&&o[x+z[i]][y+w[i]]==0)
{
o[x+z[i]][y+w[i]]=1;
search(x+z[i],y+w[i]);    
}    

}
}

 


 

这道是Lake counting S的dfs部分,其中寻找的是W的连通块,
连通的条件是经典的九 宫格,所以用了8个移动来寻找连通,
这道题寻找的是连通块的数目,所以在dfs中除了标记连通过的点,
防止再找一遍这个大块,其余不用做什么。在主函数部分计数就好。


int f[1010][1010],o[1010][1010],h[1010000],p[1010000];
char s[1010][1010];
int n,m,k,sum,u;
int z[4]={-1,1,0,0},w[4]={0,0,-1,1};
void search(int x,int y)
{
if(x==0||y==0||x>n||y>m)
{
return;
}
for(int i=0;i<4;i++)
{    
if(s[x+z[i]][y+w[i]]=='*')
sum++;
if(s[x+z[i]][y+w[i]]=='.'&&o[x+z[i]][y+w[i]]==0)
{
u++;
h[u]=x+z[i];
p[u]=y+w[i];
o[x+z[i]][y+w[i]]=1;
search(x+z[i],y+w[i]);    
}    

}
}

 


 

这道是igor in the museum,图中为‘.’和‘*’
找到是每一个连通块中‘.’链接‘*’的数目之和
所以用sum来记录这个块,用u和h[u]以及p[u]来记录一个连通块中的所有点,
方便他们统一sum。主函数中这里的统一使用与调配如下。


 

for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='.'&&o[i][j]==0)
{
u++;
o[i][j]=1;
h[u]=i;
p[u]=j;
search(i,j);
for(int v=1;v<=u;v++)
{
f[h[v]][p[v]]=sum;
}
}
sum=0;u=0;
}
}

 


 

最后一份01迷宫,算是上一个的简化,因为只用到了u来统计连通内点的数量,没用到sum。

 


 

int f[1010][1010],o[1010][1010],h[1010000],p[1010000];
char s[1010][1010];
int n,k,sum,u;
int z[4]={-1,1,0,0},w[4]={0,0,-1,1};
void search(int x,int y)
{
if(x==0||y==0||x>n||y>n)
{
return;
}
for(int i=0;i<4;i++)
{    
if(s[x+z[i]][y+w[i]]=='1'&&s[x][y]=='0'&&o[x+z[i]][y+w[i]]==0||s[x+z[i]][y+w[i]]=='0'&&s[x][y]=='1'&&o[x+z[i]][y+w[i]]==0)
{
u++;
h[u]=x+z[i];
p[u]=y+w[i];
o[x+z[i]][y+w[i]]=1;
search(x+z[i],y+w[i]);    
}    

}
}

 


 

到此结束,简单的连通问题总结完成啦。

posted @ 2020-07-22 15:30  explorerxx  阅读(182)  评论(0编辑  收藏  举报