zoukankan      html  css  js  c++  java
  • BZOJ2132: 圈地计划

    2132: 圈地计划

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 338  Solved: 243
    [Submit][Status]

    Description

    最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地。据了解,这块土地是一块矩形的区域,可以纵横划分为N×M块小区域。GDOI要求将这些区域分为商业区和工业区来开发。根据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值。更具体点,对于第i行第j列的区域,建造商业区将得到Aij收益,建造工业区将得到Bij收益。另外不同的区域连在一起可以得到额外的收益,即如果区域(I,j)相邻(相邻是指两个格子有公共边)有K块(显然K不超过4)类型不同于(I,j)的区域,则这块区域能增加k×Cij收益。经过Tiger.S教授的勘察,收益矩阵A,B,C都已经知道了。你能帮GDOI求出一个收益最大的方案么?

    Input

    输入第一行为两个整数,分别为正整数N和M,分别表示区域的行数和列数;第2到N+1列,每行M个整数,表示商业区收益矩阵A;第N+2到2N+1列,每行M个整数,表示工业区收益矩阵B;第2N+2到3N+1行,每行M个整数,表示相邻额外收益矩阵C。第一行,两个整数,分别是n和m(1≤n,m≤100);

    Output

    输出只有一行,包含一个整数,为最大收益值。

    Sample Input

    3 3
    1 2 3
    4 5 6
    7 8 9
    9 8 7
    6 5 4
    3 2 1
    1 1 1
    1 3 1
    1 1 1

    Sample Output

    81
    【数据规模】
    对于100%的数据有N,M≤100

    HINT

     

    Source

    题解:

    vfleaking在贴吧中说:

    如果v向u连一条容量为w的有向边,表示v如果在S割,那么u不在S割会产生w的代价。
    一个等价的表述是,u如果在T割,那么v不在T割会产生w的代价。注意v如果在T割,那么u在S割是不会产生代价的。
    特别的,如果v向u连一条容量为正无穷大的有向边,表示v如果在S割,那么u一定也要在S割。
    一个等价的表述是,u如果在T割,那么v一定也要在T割。

    具体是单向边还是双向边取决于你要实现的功能。

    unis96说:

    (定义 取=商业区);取黑点<=>在S割;取白点<=>在T割;S、T连的边意义显然,对于每个点u,只需要在网络流的图里面表述出:

    取了u且取了v要扣分、不取u不取v要扣分。这样建出来图来就好了,不要多考虑单向双向的问题。。

    我的补充:

    为了体现u与v同取或同不取的时候扣分,所以要二分图染色,收益连s和t相反(具体看代码),

    扣分的时候就是图中两点不在一个割的时候扣分,而实际上此时两者是同取或同不取。

    happiness那题不用二分图染色是因为选的不同的时候要扣分,所以直接一视同仁即可。

    代码:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<iostream>
     7 #include<vector>
     8 #include<map>
     9 #include<set>
    10 #include<queue>
    11 #include<string>
    12 #define inf 1000000000
    13 #define maxn 100000
    14 #define maxm 500000
    15 #define eps 1e-10
    16 #define ll long long
    17 #define pa pair<int,int>
    18 #define rep(x,y) for(int i=1;i<=x;i++)for(int j=1;j<=y;j++)
    19 #define FOR for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
    20 #define mod 1000000007
    21 using namespace std;
    22 inline int read()
    23 {
    24     int x=0,f=1;char ch=getchar();
    25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    26     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
    27     return x*f;
    28 }
    29 int  n,m,s,t,maxflow,cnt=1,tot,a[105][105],b[105][105],mark[105][105],head[maxn],cur[maxn],h[maxn],q[maxn];
    30 struct edge{int go,next,v;}e[maxm];
    31 void ins(int x,int y,int z){e[++cnt].go=y;e[cnt].v=z;e[cnt].next=head[x];head[x]=cnt;}
    32 void insert(int x,int y,int z){ins(x,y,z);ins(y,x,0);}
    33 void ins2(int x,int y,int z){insert(x,y,z);insert(y,x,z);}
    34 bool bfs()
    35 {
    36     for(int i=s;i<=t;i++)h[i]=-1;
    37     int l=0,r=1;q[1]=s;h[s]=0;
    38     while(l<r)
    39     {
    40         int x=q[++l];
    41         for(int i=head[x];i;i=e[i].next)
    42          if(e[i].v&&h[e[i].go]==-1)
    43          {
    44             h[e[i].go]=h[x]+1;q[++r]=e[i].go;
    45          }
    46     }
    47     return h[t]!=-1;
    48 }
    49 int dfs(int x,int f)
    50 {
    51     if(x==t) return f;
    52     int tmp,used=0;
    53     for(int i=head[x];i;i=e[i].next)
    54      if(e[i].v&&h[e[i].go]==h[x]+1)
    55     {
    56         tmp=dfs(e[i].go,min(e[i].v,f-used));
    57         e[i].v-=tmp;if(e[i].v)cur[x]=i;
    58         e[i^1].v+=tmp;used+=tmp;
    59         if(used==f)return f;       
    60     }
    61     if(!used) h[x]=-1;
    62     return used;
    63 }
    64 void dinic()
    65 {
    66     maxflow=0;
    67     while(bfs())
    68     {
    69         for (int i=s;i<=t;i++)cur[i]=head[i];maxflow+=dfs(s,inf);
    70     }
    71 }
    72 int main()
    73 {
    74     freopen("input.txt","r",stdin);
    75     freopen("output.txt","w",stdout);
    76     n=read();m=read();
    77     FOR mark[i][j]=(i-1)*m+j;
    78     s=0;t=mark[n][m]+1;
    79     FOR {int x=read();tot+=x;if((i+j)&1)insert(s,mark[i][j],x);else insert(mark[i][j],t,x);}
    80     FOR {int x=read();tot+=x;if((i+j)&1)insert(mark[i][j],t,x);else insert(s,mark[i][j],x);}
    81     FOR
    82     {
    83         int x=read();
    84         if(i+1<=n)ins2(mark[i][j],mark[i+1][j],x),tot+=x;
    85         if(i-1>=1)ins2(mark[i][j],mark[i-1][j],x),tot+=x;
    86         if(j+1<=m)ins2(mark[i][j],mark[i][j+1],x),tot+=x;
    87         if(j-1>=1)ins2(mark[i][j],mark[i][j-1],x),tot+=x;
    88     }
    89     dinic();
    90     printf("%d
    ",tot-maxflow);
    91     return 0;
    92 }
    View Code

    做这种题,要从最小割的含义入手,并且要学会补集转化。

  • 相关阅读:
    Linux文件属性
    [Oracle] Listener的动态注册
    jQuery easyUI Pagination控件自定义div分页(不用datagrid)
    桂林电子科技大学出校流量控制器Android版1.0.0
    php使用check box
    Python windows ping
    Python selenium chrome 环境配置
    Linux wget auto login and backup database
    PyQt4 ShowHMDB show sqlite3 with QTableWidget summary
    PyQt4 py2exe 打包 HardwareManager
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4033358.html
Copyright © 2011-2022 走看看