• BZOJ2668: [cqoi2012]交换棋子


    题解:

    可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html

    其实自己yy一下就知道这样建图的正确性了。

    感觉太神奇,居然还能拆成3个点

    orzzzzzzzzzzzzzzzzzzzzzzzzz

    跪跪跪跪跪跪跪跪

    代码:

      1 #include<cstdio>
      2   
      3 #include<cstdlib>
      4   
      5 #include<cmath>
      6   
      7 #include<cstring>
      8   
      9 #include<algorithm>
     10   
     11 #include<iostream>
     12   
     13 #include<vector>
     14   
     15 #include<map>
     16   
     17 #include<set>
     18   
     19 #include<queue>
     20   
     21 #include<string>
     22   
     23 #define inf 1000000000
     24   
     25 #define maxn 200000+5
     26   
     27 #define maxm 200000+5
     28   
     29 #define eps 1e-10
     30   
     31 #define ll long long
     32   
     33 #define pa pair<int,int>
     34   
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36   
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38   
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40   
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42   
     43 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next)
     44   
     45 #define mod 1000000007
     46   
     47 using namespace std;
     48   
     49 inline int read()
     50   
     51 {
     52   
     53     int x=0,f=1;char ch=getchar();
     54   
     55     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     56   
     57     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     58   
     59     return x*f;
     60   
     61 }
     62 int n,m,k,mincost,tot,s,t,head[maxn],d[maxn],from[2*maxm];
     63 bool v[maxn];
     64 queue<int>q;
     65 int a[100][100][3],num[100][100][3],cnt[3];
     66 struct edge{int from,go,next,v,c;}e[2*maxm];
     67 void add(int x,int y,int v,int c)
     68 {
     69     e[++tot]=(edge){x,y,head[x],v,c};head[x]=tot;
     70     e[++tot]=(edge){y,x,head[y],0,-c};head[y]=tot;
     71 }
     72 bool spfa()
     73 {
     74     for (int i=s;i<=t;i++){v[i]=0;d[i]=inf;}
     75     q.push(s);d[s]=0;v[s]=1;
     76     while(!q.empty())
     77     {
     78         int x=q.front();q.pop();v[x]=0;
     79         for (int i=head[x],y;i;i=e[i].next)
     80          if(e[i].v&&d[x]+e[i].c<d[y=e[i].go])
     81          {
     82             d[y]=d[x]+e[i].c;from[y]=i;
     83             if(!v[y]){v[y]=1;q.push(y);}
     84          }
     85     }
     86     return d[t]!=inf;
     87 }
     88 void mcf()
     89 {
     90     mincost=0;
     91     while(spfa())
     92     {
     93         int tmp=inf;
     94         for(int i=from[t];i;i=from[e[i].from]) tmp=min(tmp,e[i].v);
     95         mincost+=d[t]*tmp;
     96         for(int i=from[t];i;i=from[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;}
     97     }
     98 }
     99 const int dx[8]={0,0,1,-1,1,1,-1,-1};
    100 const int dy[8]={1,-1,0,0,-1,1,1,-1};
    101   
    102 int main()
    103   
    104 {
    105     n=read();m=read();s=0;t=3*n*m+1;
    106     for0(k,2)for1(i,n)for1(j,m)
    107     {
    108         char ch=getchar();
    109         while(ch<'0'||ch>'9')ch=getchar();
    110         a[i][j][k]=ch-'0';
    111         //cout<<i<<' '<<j<<' '<<k<<' '<<a[i][j][k]<<endl;
    112         num[i][j][k]=++tot;
    113         cnt[k]+=a[i][j][k];
    114     }
    115     //cout<<tot<<' '<<s<<' '<<t<<endl;
    116     tot=1;
    117     for1(i,n)for1(j,m)
    118     {
    119         if(a[i][j][0]&&a[i][j][1])a[i][j][0]=a[i][j][1]=0;
    120         if(a[i][j][0])
    121         {
    122             add(num[i][j][1],num[i][j][0],a[i][j][2]/2,0);
    123             add(num[i][j][0],num[i][j][2],(a[i][j][2]+1)/2,0);
    124             add(s,num[i][j][0],1,0);
    125         }
    126         else if(a[i][j][1])
    127         {
    128             add(num[i][j][1],num[i][j][0],(a[i][j][2]+1)/2,0);
    129             add(num[i][j][0],num[i][j][2],a[i][j][2]/2,0);
    130             add(num[i][j][0],t,1,0);
    131         }
    132         else
    133         {
    134             add(num[i][j][1],num[i][j][0],a[i][j][2]/2,0);
    135             add(num[i][j][0],num[i][j][2],a[i][j][2]/2,0);
    136         }
    137         for0(k,7)
    138         {
    139             int x=i+dx[k],y=j+dy[k];
    140             if(x<1||x>n||y<1||y>m)continue;
    141             add(num[i][j][2],num[x][y][1],inf,1);
    142         }
    143     }
    144     if(cnt[0]!=cnt[1]){printf("-1
    ");return 0;}
    145     mcf();
    146     printf("%d
    ",mincost);
    147   
    148     return 0;
    149   
    150 }  
    View Code

    2668: [cqoi2012]交换棋子

    Time Limit: 3 Sec  Memory Limit: 128 MB
    Submit: 673  Solved: 235
    [Submit][Status]

    Description

    有一个nm列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态。要求第i行第j列的格子只能参与mi,j次交换。

    Input

    第一行包含两个整数nm(1<=n, m<=20)。以下n行为初始状态,每行为一个包含m个字符的01串,其中0表示黑色棋子,1表示白色棋子。以下n行为目标状态,格式同初始状态。以下n行每行为一个包含m个0~9数字的字符串,表示每个格子参与交换的次数上限。
     

    Output

    输出仅一行,为最小交换总次数。如果无解,输出-1。

    Sample Input

    3 3
    110
    000
    001
    000
    110
    100
    222
    222
    222

    Sample Output

    4
  • 相关阅读:
    Android直方图递增View
    分析实现Android自定义View之扇形图
    可折叠的ToolBar+抽屉菜单NavigationView+浮动按钮FloatButton
    走着官方的教程入门Material Design(一)
    AndroidStudio — Error:Failed to resolve: junit:junit:4.12错误解决
    Win10提示没有权限使用网络资源问题解决
    Android Socket连接PC出错问题及解决
    Android Studio —— 创建Menu菜单项
    Eclipse出现"Running Android Lint has encountered a problem"解决方案
    关于leal和mov
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4182161.html
Copyright © 2020-2023  润新知