• 【网络流24题】方格取数问题


    【网络流24题】方格取数问题

    Description

    在一个有m * n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。

    Input

    第1 行有2 个正整数m和n,分别表示棋盘的行数和列数。 
    接下来的m行,每行有n个正整数,表示棋盘方格中的数。

    Output

    将取数的最大总和输出

    Sample Input

    3 3 
    1 2 3 
    3 2 3 
    2 3 1

    Sample Output

    11

    Hint

    数据范围: 
    1<=N,M<=30

    Source

    网络流 

     

    二分图点权最大独立集, 网络最小割


    思路:取出的点要互不相交,所以考虑用二分图来做。同时这是个裸的最大点权独立集独立集问题,可以用最小点权覆盖集来做。把点黑白染色,S->黑色点(w=黑色点方格上数字),白色点->T(w=白色点方格上数字),同时黑色点->与他相邻的白色点(w=inf)。所有点权之和-流量即为答案

     1 // It is made by XZZ
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #define File
     6 #define Fname "grid"
     7 using namespace std;
     8 #define rep(a,b,c) for(rg int a=b;a<=c;a++)
     9 #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    10 #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    11 #define il inline
    12 #define rg register
    13 #define vd void
    14 #define t (dis[i])
    15 typedef long long ll;
    16 il int gi(){
    17     rg int x=0;rg char ch=getchar();
    18     while(ch<'0'||ch>'9')ch=getchar();
    19     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    20     return x;
    21 }
    22 const int maxn=30*30+10,maxm=30*30*4+100,S=1,T=2;
    23 int fir[maxn],nxt[maxm],dis[maxm],w[maxm],id=1;
    24 int X[]={23333,0,0,1,-1},Y[]={23333,1,-1,0,0};
    25 il vd add(int a,int b,int c){
    26     nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;
    27     if(c)add(b,a,0);
    28 }
    29 int num[31][31];
    30 bool vis[maxn];
    31 il int ff(int now,int end,int minn){
    32     if(now==end)return minn;
    33     vis[now]=1;
    34     erep(i,now)
    35     if(!vis[dis[i]]&&w[i]){
    36         rg int down=ff(dis[i],end,min(minn,w[i]));
    37         if(down){w[i]-=down,w[i^1]+=down;return down;}
    38     }
    39     return 0;
    40 }
    41 int main(){
    42     freopen(Fname".in","r",stdin);
    43     freopen(Fname".out","w",stdout);
    44     int n=gi(),m=gi(),Id=2,sum=0,a=0;
    45     rep(i,1,n)rep(j,1,m){
    46     num[i][j]=++Id;
    47     sum+=a=gi();
    48     if((i+j)&1)add(S,num[i][j],a);
    49     else add(num[i][j],T,a);
    50     }
    51     rep(i,1,n)rep(j,1,m)if((i+j)&1)rep(k,1,4)
    52     if(num[i+X[k]][j+Y[k]])add(num[i][j],num[i+X[k]][j+Y[k]],666666666);
    53     int flow,Flow=0;
    54     while(flow=ff(S,T,666666666))Flow+=flow,memset(vis,0,sizeof vis);
    55     printf("%d
    ",sum-Flow);
    56     return 0;
    57 }
    View Code

    PS.题目太水了,用了FF,依然2ms。。。

  • 相关阅读:
    单链表
    队列
    产品经理们,遇到Bug请别十万火急
    2008年7月3日
    JS URL 参数
    NET 产品版权保护方案 (.NET源码加密保护)
    常用正则表达式
    网线接法
    C#创建多文档的界面
    TGE学习笔记04 billboard
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7193733.html
Copyright © 2020-2023  润新知