zoukankan      html  css  js  c++  java
  • 【BZOJ】【2668】【CQOI2012】交换棋子

    网络流/费用流


      跪跪跪,居然还可以这样建图……

      题解:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html

    考虑每个点的交换限制的约束,一看就知道是点容量,但是这里不是一分为二,而是一分为三。

    首先我们把问题化简,变成对于原图上所有黑点,找到一个新图中的黑点,进行多次交换后到达。我们看到多次交换实际上是走了一条路径(这里不是最短 路)。对于这条路径的起点和终点,仅进行了1次交换,而路径上的其他点都交换了2次。所以我们需要构造一种图来把这个交换次数的差异体现出来,于是:

    对于每个点一分为三,分为p0,p1,p2,对于每个点,如果它是原图中得黑点,连 边<p1,p0,c/2,0>,<p0,p2,(c+1)/2>,<st,p0,1,0>;如果它是新图中得黑点, 连边<p1,p0,(c+1)/2>,<p0,p2,c/2,0>,<p0,ed,1,0>;如果它在两个图中都是 白点,那么连边<p1,p0,c/2,0>,<p0,p2,c/2,0>。这样就可以体现出点容量的差异了。

    然后对于原图中可以交换的两个点(i,j)连接<pi2,pj1,inf,1>,那么这种边每流过1的流量就意味着(i,j)交换了一次,那么费用就是最终的答案了。

      1 /**************************************************************
      2     Problem: 2668
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:24 ms
      7     Memory:48464 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 2668
     11 #include<cmath>
     12 #include<vector>
     13 #include<cstdio>
     14 #include<cstring>
     15 #include<cstdlib>
     16 #include<iostream>
     17 #include<algorithm>
     18 #define rep(i,n) for(int i=0;i<n;++i)
     19 #define F(i,j,n) for(int i=j;i<=n;++i)
     20 #define D(i,j,n) for(int i=j;i>=n;--i)
     21 #define pb push_back
     22 using namespace std;
     23 inline int getint(){
     24     int v=0,sign=1; char ch=getchar();
     25     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     26     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
     27     return v*sign;
     28 }
     29 const int N=20010,M=2000000,INF=~0u>>2;
     30 typedef long long LL;
     31 /******************tamplate*********************/
     32 char s1[50][50],s2[50][50],s3[50][50];
     33 int n,m,a[50][50],b[50][50],c[50][50],num[50][50],b1,b2,ans,flow,tot;
     34 inline int gcd(int a,int b){return b ? gcd(b,a%b) : a;}
     35 bool judge(int x,int y){
     36     int q=x*x-y*y,s=sqrt(q);
     37     if (s*s==q && gcd(y,s)==1) return 1;
     38     return 0;
     39 }
     40 struct edge{int from,to,v,c;};
     41 struct Net{
     42     edge E[M];
     43     int head[N],next[M],cnt;
     44     void ins(int x,int y,int z,int c){
     45         E[++cnt]=(edge){x,y,z,c};
     46         next[cnt]=head[x]; head[x]=cnt;
     47     }
     48     void add(int x,int y,int z,int c){
     49         ins(x,y,z,c); ins(y,x,0,-c);
     50     }
     51     int from[N],Q[M],d[N],S,T;
     52     bool inq[N];
     53     bool spfa(){
     54         int l=0,r=-1;
     55         F(i,0,T) d[i]=INF;
     56         d[S]=0; Q[++r]=S; inq[S]=1;
     57         while(l<=r){
     58             int x=Q[l++];
     59             inq[x]=0;
     60             for(int i=head[x];i;i=next[i])
     61                 if(E[i].v>0 && d[x]+E[i].c<d[E[i].to]){
     62                     d[E[i].to]=d[x]+E[i].c;
     63                     from[E[i].to]=i;
     64                     if (!inq[E[i].to]){
     65                         Q[++r]=E[i].to;
     66                         inq[E[i].to]=1;
     67                     }
     68                 }
     69         }
     70         return d[T]!=INF;
     71     }
     72     void mcf(){
     73         int x=INF,y,z;
     74         for(int i=from[T];i;i=from[E[i].from])
     75             x=min(x,E[i].v);
     76         for(int i=from[T];i;i=from[E[i].from]){
     77             E[i].v-=x;
     78             E[i^1].v+=x;
     79         }
     80         flow+=x;
     81         ans+=x*d[T];
     82     }
     83     void init(){
     84         n=getint(); m=getint(); cnt=1;
     85         tot=n*m; S=0; T=tot*3+1;
     86         F(i,1,n) scanf("%s",s1[i]+1);
     87         F(i,1,n) scanf("%s",s2[i]+1);
     88         F(i,1,n) scanf("%s",s3[i]+1);
     89         F(i,1,n) F(j,1,m){
     90             a[i][j]=s1[i][j]-'0'; if(a[i][j]) b1++;
     91             b[i][j]=s2[i][j]-'0'; if(b[i][j]) b2++;
     92             c[i][j]=s3[i][j]-'0';
     93             if (a[i][j]&&b[i][j]) a[i][j]=b[i][j]=0,b1--,b2--;
     94         }
     95         F(i,1,n) F(j,1,m){
     96             int now=(i-1)*m+j;
     97             num[i][j]=now;
     98             if (a[i][j]){
     99                 add(S,now,1,0);
    100                 add(tot+now,now,c[i][j]/2,0);
    101                 add(now,2*tot+now,(c[i][j]+1)/2,0);
    102             }else if(b[i][j]){
    103                 add(now,T,1,0);
    104                 add(tot+now,now,(c[i][j]+1)/2,0);
    105                 add(now,2*tot+now,c[i][j]/2,0);
    106             }else{
    107                 add(tot+now,now,c[i][j]/2,0);
    108                 add(now,2*tot+now,c[i][j]/2,0);
    109             }
    110         }
    111         F(i,1,n) F(j,1,m){
    112             if (i>1) add(2*tot+num[i][j],tot+num[i-1][j],INF,1);
    113             if (j>1) add(2*tot+num[i][j],tot+num[i][j-1],INF,1);
    114             if (i<n) add(2*tot+num[i][j],tot+num[i+1][j],INF,1);
    115             if (j<m) add(2*tot+num[i][j],tot+num[i][j+1],INF,1);
    116             if (i>1 && j>1) add(2*tot+num[i][j],tot+num[i-1][j-1],INF,1);
    117             if (i<n && j<m) add(2*tot+num[i][j],tot+num[i+1][j+1],INF,1);
    118             if (i>1 && j<m) add(2*tot+num[i][j],tot+num[i-1][j+1],INF,1);
    119             if (i<n && j>1) add(2*tot+num[i][j],tot+num[i+1][j-1],INF,1);
    120         }
    121         if (b1==b2){
    122             while(spfa()) mcf();
    123             if (flow!=b1) ans=-1;
    124         }else ans=-1;
    125         printf("%d
    ",ans);
    126     }
    127 }G1;
    128  
    129 int main(){
    130 #ifndef ONLINE_JUDGE
    131     freopen("input.txt","r",stdin);
    132 //  freopen("2668.out","w",stdout);
    133 #endif
    134     G1.init();
    135     return 0;
    136 }
    View Code
  • 相关阅读:
    javascript:void(0)是什么意思 天高地厚
    C#开发 WinForm中窗体显示和窗体传值相关知识
    c#在WinForm中重写ProgressBar控件(带%的显示)
    flash在C#中的应用
    c# winform 关于DataGridView的一些操作
    winform中输入数据的验证
    RadioButton和CheckBox
    Manifest文件的配置
    简单程序用于熟悉Activity生命周期
    Activity的生命周期
  • 原文地址:https://www.cnblogs.com/Tunix/p/4354305.html
Copyright © 2011-2022 走看看