能在线性时间内求出图中的连通块数量
eg 1:acwing 1098
城堡问题
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=55,M=N*N;
int n,m;
#define x first
#define y second
int g[N][N];
bool st[N][N];
pii q[M];
int bfs(int sx,int sy)
{
int dx[]={0,-1,0,1},dy[]={-1,0,1,0};
int maxs=0;
int hh=0,tt=0;
q[tt]={sx,sy};
st[sx][sy]=true;
while(tt>=hh)
{
auto A=q[hh++];
maxs++;
for(int i=0;i<4;i++)
{
int a=A.x+dx[i],b=A.y+dy[i];
if(a<0 || a>=n || b<0 || b>=m) continue;
if(st[a][b]) continue;
if(g[A.x][A.y] >> i & 1) continue;//判断是不是有墙 看的是g中二进制数的第i位是不是1
q[++tt] = {a,b};
st[a][b]=true;
}
}
return maxs;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>g[i][j];
int cnt=0,maxs=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(!st[i][j])
{
cnt++;
maxs=max(maxs,bfs(i,j));
}
cout<<cnt<<endl;
cout<<maxs<<endl;
return 0;
}
eg2: acwing 1106
山峰山谷
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> pii;
const int N = 1010,M=N*N;
int h[N][N];
int n;
bool st[N][N];
pii q[M];
void bfs(int sx,int sy,bool& has_higher,bool& has_lower)
{
int hh=0,tt=0;
q[0]={sx,sy};
st[sx][sy]=1;
while(tt>=hh)
{
auto t=q[hh++];
for(int i=t.x-1;i<=t.x+1;i++)
for(int j=t.y-1;j<=t.y+1;j++)
{
//if(st[i][j]) continue 不能写这句 因为在边界时 就算st==1
// 也需要考虑峰谷的问题
if(i<0||i>=n||j<0||j>=n) continue;
if((h[i][j]!=h[t.x][t.y]))
{
if(h[i][j]>h[t.x][t.y]) has_higher=1;
else has_lower=1;
}
else if(!st[i][j])
{
q[++tt] = {i,j};
st[i][j]=true;
}
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++) cin>>h[i][j];
int peak=0,valley=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(!st[i][j])
{
bool has_higher=false,has_lower=false;
bfs(i,j,has_higher,has_lower);
if(!has_higher) peak++;
if(!has_lower) valley++;
}
cout<<peak<<" "<<valley<<endl;
return 0;
}