• [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
    ",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
    ",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
    ",ans>>1);
    84 }
    View Code
  • 相关阅读:
    MVC之路由规则 (自定义,约束,debug)
    MCV之行为
    mvc之页面强类型
    Jquery异步上传图片
    三层VS控制器
    Oracle 表分区
    C#编写的通过汉字得到拼音和五笔码
    MYSQL存储过程学习
    Sina App Engine(SAE)入门教程(9)- SaeMail(邮件)使用
    状态CSS
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5621735.html
Copyright © 2020-2023  润新知