https://www.luogu.com.cn/problem/P1457

题意:一个矩阵统计“连通块”个数和大小(用“墙”分隔),再求去掉哪堵墙后得到最大”连通块“。

统计“连通块个数“ 和大小 直接跑一边 BFS 即可,然后从左往右,从下往上(先北后东)暴力枚举每堵墙,拆掉后求”连通块“大小,取最大值即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
const int MAX=55;
int n,m,t,a[MAX][MAX],c,vis[MAX][MAX];
int f[4]={8,4,2,1};
int aw[4][2]={1,0,0,1,-1,0,0,-1};
int cnt,_max,_max2,ex,ey,flag,tmp;
struct node{
int x,y;
node(int _x,int _y){
x=_x;y=_y;
}
};
bool judge(int x,int y){
if(x<1||x>n||y<1||y>m) return false;
return true;
}
int bfs(int x,int y){
queue<node>q;
int ans=0,tx,ty;
if(vis[x][y]) return 0;
vis[x][y]=1;
q.push(node(x,y));
while(!q.empty()){
node t=q.front();
q.pop();
ans ++;
c=a[t.x][t.y] ;
fi(i,0,4){
if(c>=f[i]){
c-=f[i];
}else {
tx=t.x+aw[i][0];ty=t.y+aw[i][1];
if(judge(tx,ty)&&!vis[tx][ty]){
q.push(node(tx,ty));
vis[tx][ty]=1;
}
}
}
}
return ans;
}
bool haveWall(int x,int y,int f){
int c=a[x][y];
if(c>=8) c-=8;
if(c>=4){
if(f==1) return true;
else c-=4;
}
if(c>=2){
if(f==2) return true;
else c-=2;
}
return false;
}
int main(){
freopen("in","r",stdin);
sf(m);sf(n);
fi(i,1,n+1)
fi(j,1,m+1){
sf(a[i][j]);
}
mem(vis,0);
fi(i,1,n+1)
fi(j,1,m+1){
tmp=bfs(i,j);
if(tmp) cnt++;
_max=max(_max,tmp);
}
int last=0;
fi(j,1,m+1)
fd(n+1,1){
// 北 2 东 1
for(int k=2;k>=1;k--){
mem(vis,0);
if(haveWall(i,j,k)){
a[i][j]-=f[k];//拆墙
tmp=bfs(i,j);
a[i][j]+=f[k];//复原
if(tmp > last){
last=tmp;
_max2=tmp;
ex=i;ey=j;flag=k;
}
}
}
}
printf("%d\n%d\n%d\n%d %d ",cnt,_max,_max2,ex,ey);
if(flag==1) pfc("E");
else pfc("N");
return 0;
}