这题非常巧妙。这里可以把一块连续区域染色很容易误导做题者。实际上这题的做法是转换成最短路。
为什么呢?仔细想一想,对于这个点,和它同一次涂色的点一定是和它上下左右相邻的点连通的点。
每新涂色一次贡献就要+1,那么什么时候新涂色一次呢?显然是这个点和它相邻的点颜色不同的时候就要新涂色一次。
于是我们对于每个点和它上下左右的点连边,当两点颜色相同时边权为0,否则为1。然后我们以每个点开头跑一边dij,记录一下所有黑色点的最大路径长度,答案就是这些长度的最小值+1。
为什么是黑色呢?因为初始是白色。
为什么要+1呢?因为你默认起点的dis是0,但那实际上是第一次涂色。特殊情况就是全为白色,所以Maxn初始值为-1。
1 #include<stdio.h>
2 #include<queue>
3 #define it register int
4 #define il inline
5 using namespace std;
6 const int N=1000005;
7 const int dx[]={0,0,1,-1};
8 const int dy[]={1,-1,0,0};
9 char s[55][55];
10 int n,m,ans,d[N],h[N],nxt[N],adj[N],w[N],t,cnt,bh[55][55];
11 struct ky{
12 int u,dis;
13 bool operator<(const ky &p)const{
14 return dis>p.dis;
15 }
16 };
17 priority_queue<ky> q;
18 il void add(it u,it v,it x){
19 nxt[++t]=h[u],h[u]=t,adj[t]=v,w[t]=x;
20 }
21 il int Min(it p,it q){
22 return p<q?p:q;
23 }
24 il int Max(it p,it q){
25 return p>q?p:q;
26 }
27 il void dij(it st){
28 for(it i=1;i<=cnt;++i) d[i]=1e9;
29 d[st]=0,q.push((ky){st,0});
30 register ky top;
31 while(!q.empty()){
32 top=q.top();q.pop();
33 if(top.dis^d[top.u]) continue;
34 for(it i=h[top.u],j;i;i=nxt[i])
35 if(d[j=adj[i]]>top.dis+w[i]) d[j]=top.dis+w[i],q.push((ky){j,d[j]});
36 }
37 it maxn=-1;
38 for(it i=1;i<=n;++i)
39 for(it j=1;j<=m;++j)
40 if(s[i][j]=='B') maxn=Max(maxn,d[bh[i][j]]);
41 ans=Min(ans,maxn+1);
42 }
43 int main(){
44 scanf("%d%d",&n,&m);
45 for(it i=1;i<=n;++i) scanf("%s",s[i]+1);
46 for(it i=1;i<=n;++i)
47 for(it j=1;j<=m;++j)
48 bh[i][j]=++cnt;
49 for(it i=1,tx,ty;i<=n;++i)
50 for(it j=1;j<=m;++j)
51 for(it k=0;k<4;++k){
52 tx=i+dx[k],ty=j+dy[k];
53 if(tx<1||tx>n||ty<1||ty>m) continue;
54 add(bh[i][j],bh[tx][ty],s[i][j]!=s[tx][ty]);
55 }
56 ans=0x7fffffff;
57 for(it i=1;i<=cnt;++i) dij(i);
58 printf("%d",ans);
59 return 0;
60 }