1.地图周围再加一圈海
2.周长最多为sum=n*(m+1)+m*(n+1)。如果有邻接相同,要减1.最小割使相同最少。结果为sum-最小割
3.但是有E海滩,两边都能选。让E到S,T都连一个很大的数(10000,比最小割大就行)。这样最小割时两个10000一定要选一个。那么在sum中也加上10000就能消除。这样一定割一边而且不都割。而且连S,和T都为一样的数能确保消去E的决策的干扰。
剩下的就和套路一样了,奇偶建图,偶数时,'.'连S INF,'D'连T INF,E连S,T 10000。邻接互相连1。
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <iomanip> #include <cstring> #include <map> #include <queue> #include <set> #include <cassert> #include <stack> #include <bitset> #define mkp make_pair using namespace std; const double EPS=1e-12; typedef long long lon; const lon SZ=51,SSZ=12*SZ*SZ,APB=10000,one=1,INF=0x7FFFFFFF,mod=1000000007; lon n,m,S=2501,T=2502,sum,cnt,head[SZ*SZ]; lon nex[SSZ],to[SSZ],wt[SSZ],dep[SSZ]; int dx[]={0,1},dy[]={1,0}; char ch[SZ][SZ]; void add(int u,int v,int w) { ++cnt; nex[cnt]=head[u]; head[u]=cnt; to[cnt]=v,wt[cnt]=w; } int getid(int i,int j) { return (i-1)*(m+2)+j; } void init() { cin>>n>>m; sum=n*(m+1)+m*(n+1),cnt=-1; memset(head,-1,sizeof(head)); for(int i=1;i<=n+2;++i) { for(int j=1;j<=m+2;++j) { if(i==1||j==1||i==n+2||j==m+2) { ch[i][j]='D'; } else { cin>>ch[i][j]; if(ch[i][j]=='E')sum+=APB; } } } for(int i=1;i<=n+2;++i) { for(int j=1;j<=m+2;++j) { if(!((i+j)&1)) { if(ch[i][j]=='.') { add(S,getid(i,j),INF); add(getid(i,j),S,0); } else if(ch[i][j]=='D') { add(getid(i,j),T,INF); add(T,getid(i,j),0); } else { add(S,getid(i,j),APB); add(getid(i,j),S,0); add(getid(i,j),T,APB); add(T,getid(i,j),0); } } else { if(ch[i][j]=='.') { add(getid(i,j),T,INF); add(T,getid(i,j),0); } else if(ch[i][j]=='D') { add(S,getid(i,j),INF); add(getid(i,j),S,0); } else { add(S,getid(i,j),APB); add(getid(i,j),S,0); add(getid(i,j),T,APB); add(T,getid(i,j),0); } } } } for(int i=1;i<=n+1;++i) { for(int j=1;j<=m+1;++j) { for(int k=0;k<2;++k) { int nx=i+dx[k],ny=j+dy[k]; if(i==1&&nx==1||j==1&&ny==1)continue; add(getid(i,j),getid(nx,ny),1); add(getid(nx,ny),getid(i,j),0); add(getid(nx,ny),getid(i,j),1); add(getid(i,j),getid(nx,ny),0); } } } // for(int i=1;i<=n+2;++i) // { // for(int j=1;j<=m+2;++j) // { // for(int k=head[getid(i,j)];k!=-1;k=nex[k]) // { // cout<<i<<" "<<j<<" "<<to[k]<<" "<<wt[k]<<endl; // } // } // } } bool bfs() { memset(dep,0,sizeof(dep)); dep[S]=1; queue<int> q; q.push(S); for(;q.size();) { int fr=q.front(); q.pop(); for(int i=head[fr];i!=-1;i=nex[i]) { int t=to[i],w=wt[i]; if(!dep[t]&&w) { dep[t]=dep[fr]+1; q.push(t); if(t==T)return 1; } } } return 0; } int dinic(int x,int flow) { if(x==T)return flow; else { int rem=flow; for(int i=head[x];i!=-1&&rem;i=nex[i]) { int t=to[i],w=wt[i]; if(dep[t]==dep[x]+1&&w) { int tmp=dinic(t,min(w,rem)); if(!tmp)dep[t]=0; rem-=tmp; wt[i]-=tmp; wt[i^1]+=tmp; } } return flow-rem; } } void work() { int res=0; for(;bfs();) { res+=dinic(S,INF); } cout<<sum-res<<endl; } void release() { } int main() { std::ios::sync_with_stdio(0); //freopen("d:\\1.txt","r",stdin); lon casenum; cin>>casenum; //cout<<casenum<<endl; for(int time=1;time<=casenum;++time) //for(int time=1;cin>>n>>m,n;++time) { cout<<"Case "<<time<<": "; init(); work(); release(); } return 0; }