[bzoj2668] [cqoi2012]交换棋子
到现在还不是很懂。网络流这块基础太弱了QAQ
一开始先把初始状态黑白棋子数目不同的情况去掉。
然后只要关注黑色棋子就好了。
每个棋子拆点,入点往出点流量限制是m(i,j)/2,费用为2。但如果这个棋子入点是黑或者出点是黑的话就加1/2
棋子初始状态为黑的话,就从S往它入点连一条流量1,费用-1的边,结束状态为黑的话,就从它出点往T连一条同样的边。
每个棋子从出点往相邻棋子的入点连一条流量正无穷,费用为0的边。
最小交换次数就是最小费用的1/2
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 const int maxn=23*23*2,inf=1002333333; 8 const int xx[8]={-1,-1,-1,0,0,1,1,1},yy[8]={-1,0,1,-1,1,-1,0,1}; 9 struct zs{int too,pre,flow,dis;}e[233333];int tot,last[maxn]; 10 int dis[maxn],dl[1002333]; 11 int id[23][23],mx[maxn]; 12 bool u[maxn],ins[maxn],st[maxn],ed[maxn]; 13 int i,j,k,n,m,s,t,ans; 14 char ch[23]; 15 16 int ra;char rx; 17 inline int read(){ 18 rx=getchar(),ra=0; 19 while(rx<'0'||rx>'9')rx=getchar(); 20 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 21 } 22 inline bool spfa(){ 23 memset(dis,60,(t+1)<<2); 24 int l=0,r=1,i,now;dl[1]=s,dis[s]=0,u[s]=1; 25 while(l<r) 26 for(i=last[now=dl[++l]],u[now]=0;i;i=e[i].pre)if(e[i].flow&&dis[e[i].too]>dis[now]+e[i].dis){ 27 dis[e[i].too]=dis[now]+e[i].dis; 28 if(!u[e[i].too])dl[++r]=e[i].too,u[e[i].too]=1; 29 } 30 // for(i=1;i<=t;i++)printf("0-->%d %d\n",i,dis[i]); 31 return dis[t]<inf; 32 } 33 inline int min(int a,int b){return a<b?a:b;} 34 int dfs(int x,int mx){ 35 if(x==t)return mx; 36 int i,used=0,w;ins[x]=1; 37 for(i=last[x];i;i=e[i].pre)if(e[i].flow&&dis[e[i].too]==dis[x]+e[i].dis&&!ins[e[i].too]){ 38 w=dfs(e[i].too,min(mx-used,e[i].flow));if(w){ 39 e[i].flow-=w,e[i^1].flow+=w,used+=w,ans+=e[i].dis*w; 40 if(used==mx){ins[x]=0;return mx;} 41 } 42 } 43 dis[x]=inf,ins[x]=0;return used; 44 } 45 inline void insert(int a,int b,int c,int d){ 46 // printf(" %d-->%d %d %d\n",a,b,c,d); 47 e[++tot].too=b,e[tot].flow=c,e[tot].dis= d,e[tot].pre=last[a],last[a]=tot, 48 e[++tot].too=a,e[tot].flow=0,e[tot].dis=-d,e[tot].pre=last[b],last[b]=tot; 49 } 50 51 int main(){ 52 n=read(),m=read();int num1=0,num2=0,tmp=0; 53 for(i=1;i<=n;i++)for(j=1;j<=m;j++)id[i][j]=++tmp; 54 for(i=1;i<=n;i++){ 55 scanf("%s",ch+1); 56 for(j=1;j<=m;j++) 57 if(ch[j]=='1')st[id[i][j]]=1,num1++; 58 } 59 for(i=1;i<=n;i++){ 60 scanf("%s",ch+1); 61 for(j=1;j<=m;j++) 62 if(ch[j]=='1')ed[id[i][j]]=1,num2++; 63 } 64 if(num1!=num2){puts("-1");return 0;} 65 for(i=1;i<=n;i++){ 66 scanf("%s",ch+1); 67 for(j=1;j<=m;j++) 68 mx[id[i][j]]=ch[j]-'0'; 69 } 70 s=0,t=tmp<<1|1,tot=1; 71 for(i=1;i<=n;i++)for(j=1;j<=m;j++){ 72 int now=id[i][j],x,y; 73 if(st[now])insert(s,now,1,-1); 74 if(ed[now])insert(now+tmp,t,1,-1); 75 insert(now,now+tmp,(mx[now]+st[now]+ed[now])>>1,2); 76 for(k=0;k<8;k++){ 77 x=i+xx[k],y=j+yy[k]; 78 if(x<1||y<1||x>n||y>m)continue; 79 insert(now+tmp,id[x][y],inf,0); 80 } 81 }int flow=0; 82 while(spfa())flow+=dfs(s,inf); 83 if(flow<num1)puts("-1");else printf("%d\n",ans>>1); 84 }