1. 程式人生 > >CF37E Trial for Chief(最短路)

CF37E Trial for Chief(最短路)

mem aps ons stream can lose name oid 次數

題意

題意是給你一張 NMNMNM 的圖,每個點有黑色和白色,初始全為白色,每次可以把一個相同顏色的連續區域染色,求最少的染色次數;(n,m<=50)

題解

轉化為最短路。對於每一個點與它相鄰的相同顏色的點連權值為0的邊,對於顏色不同的點連權值為1的點。從每一個點跑單源最短路,把到W點的距離和到B點的距離+1取min作為此點的答案,最後把每一個點的答案取max就是答案。

對於能直接到達的兩個顏色相同的點顯然只用塗一次,如果不同就要再塗一次,所以這樣建圖。為了特判全是黑色的情況,所以到B點的距離要加一。顯然,這樣對於其他情況沒有影響。

技術分享圖片
 1 #include<iostream>
 2
#include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int INF=0x3f3f3f3f; 9 int n,m; 10 char s[600][600]; 11 int ans=INF; 12 int dis[30000],vis[30000],head[30000],cnt; 13 struct edge{ 14 int to,nxt,w; 15 }e[900000
]; 16 void add(int u,int v,int w){ 17 cnt++; 18 e[cnt].nxt=head[u]; 19 e[cnt].to=v; 20 e[cnt].w=w; 21 head[u]=cnt; 22 } 23 int zb(int x,int y){ 24 return (x-1)*m+y; 25 } 26 void spfa(int ss){ 27 queue<int> q; 28 memset(dis,0x3f,sizeof(dis)); 29 dis[ss]=0; 30 q.push(ss);
31 vis[ss]=1; 32 while(!q.empty()){ 33 int u=q.front(); 34 q.pop(); 35 vis[u]=0; 36 for(int i=head[u];i;i=e[i].nxt){ 37 int v=e[i].to; 38 if(dis[v]>dis[u]+e[i].w){ 39 dis[v]=dis[u]+e[i].w; 40 if(vis[v]==0){ 41 vis[v]=1; 42 q.push(v); 43 } 44 } 45 } 46 } 47 int tmp=-1; 48 for(int i=1;i<=n*m;i++){ 49 if(s[(i-1)/m+1][(i-1)%m+1]==B)tmp=max(tmp,dis[i]+1); 50 else tmp=max(tmp,dis[i]); 51 } 52 ans=min(ans,tmp); 53 } 54 int main(){ 55 scanf("%d%d",&n,&m); 56 for(int i=1;i<=n;i++) 57 for(int j=1;j<=m;j++){ 58 cin>>s[i][j]; 59 } 60 for(int i=1;i<=n;i++) 61 for(int j=1;j<=m;j++){ 62 if(i>1)add(zb(i,j),zb(i-1,j),(s[i][j]!=s[i-1][j])); 63 if(i<n)add(zb(i,j),zb(i+1,j),(s[i][j]!=s[i+1][j])); 64 if(j>1)add(zb(i,j),zb(i,j-1),(s[i][j]!=s[i][j-1])); 65 if(j<m)add(zb(i,j),zb(i,j+1),(s[i][j]!=s[i][j+1])); 66 } 67 for(int i=1;i<=n*m;i++){ 68 spfa(i); 69 } 70 printf("%d",ans); 71 return 0; 72 }
View Code

CF37E Trial for Chief(最短路)