[bzoj2638] 黑白染色
比较蛋疼的是我们可以先染个底色,再在底色上染别的东西。
由ccz大爷的题解可得。。将目标状态里相同颜色的联通块缩点后,枚举起点,生成树里的最大节点深度就是需要的次数了,
如果最大深度是白色的话记得-1.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=2523,xx[4]={1,-1,0,0},yy[4]={0,0,1,-1}; 7 struct zs{ 8 int too,pre; 9 }e[123333];int tot,last[maxn]; 10 struct zs1{int x,y;}dl[maxn]; 11 char mp[53][53]; 12 int id[53][53]; 13 int col[maxn],d[maxn]; 14 short dis[maxn]; 15 bool u[maxn]; 16 int i,j,k,n,m,ans,cnt; 17 18 int ra;char rx; 19 inline int read(){ 20 rx=getchar(),ra=0; 21 while(rx<'0'||rx>'9')rx=getchar(); 22 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 23 } 24 inline void insert(int a,int b){ 25 // printf("%d-->%d\n",a,b); 26 e[++tot].too=b,e[tot].pre=last[a],last[a]=tot, 27 e[++tot].too=a,e[tot].pre=last[b],last[b]=tot; 28 } 29 30 int main(){ 31 n=read(),m=read(); 32 for(i=1;i<=n;i++)scanf("%s",mp[i]+1); 33 for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(!id[i][j]){ 34 int l=0,r=1,nx,ny,x,y;dl[1]=(zs1){i,j}; 35 cnt++,col[cnt]=mp[i][j]=='B',id[i][j]=cnt; 36 while(l<r){ 37 l++,nx=dl[l].x,ny=dl[l].y; 38 for(k=0;k<4;k++){ 39 x=nx+xx[k],y=ny+yy[k]; 40 if(x<1||y<1||x>n||y>m)continue; 41 if(mp[x][y]==mp[i][j]&&!id[x][y]) 42 dl[++r]=(zs1){x,y},id[x][y]=cnt; 43 else if(id[x][y])insert(id[x][y],cnt); 44 } 45 } 46 } 47 ans=1e9; 48 for(i=1;i<=cnt;i++){ 49 memset(dis,0,(cnt+1)<<1); 50 int l=0,r=1,now,j;d[1]=i,dis[i]=1; 51 while(l<r) 52 for(j=last[now=d[++l]];j;j=e[j].pre)if(!dis[e[j].too]) 53 dis[e[j].too]=dis[now]+1,d[++r]=e[j].too; 54 ans=min(ans,dis[d[r]]-(!col[d[r]])); 55 } 56 printf("%d\n",ans); 57 }