[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 }
View Code

 

posted @ 2016-06-27 22:08  czllgzmzl  阅读(179)  评论(0编辑  收藏  举报