• [网络流24题] 方格取数问题(cogs 734)


    «问题描述:
    在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
    意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
    «编程任务:
    对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
    «数据输入:
    由文件grid.in提供输入数据。文件第1 行有2 个正整数m和n,分别表示棋盘的行数
    和列数。接下来的m行,每行有n个正整数,表示棋盘方格中的数。
    «结果输出:
    程序运行结束时,将取数的最大总和输出到文件grid.out中。
    输入文件示例 输出文件示例
    grid.in
    3 3
      1 2 3

    3 2 3

    2 3 1

    grid.out

    11

    (1<=N,M<=30)

    /*
      二分图的最大点权独立集
      先按照奇偶性把图分成一个二分图
      因为定理:最大点权独立集=V-最小点权覆盖集=V-最小割
      所以跑最大流就行了。 
    */
    #include<cstdio>
    #include<iostream>
    #define N 1010
    #define M 300010
    #define inf 1000000000
    using namespace std;
    int a[35][35],head[N],dis[N],q[N],n,m,cnt=1,S,T,ans;
    struct node{
        int v,pre,f;
    };node e[M];
    int ws(int x,int y){
        return (x-1)*m+y;
    }
    void add(int u,int v,int f){
        e[++cnt].v=v;e[cnt].f=f;e[cnt].pre=head[u];head[u]=cnt;
        e[++cnt].v=u;e[cnt].f=0;e[cnt].pre=head[v];head[v]=cnt;
    }
    bool bfs(){
        for(int i=1;i<=T;i++)dis[i]=inf;
        int h=0,t=1;q[1]=S;dis[S]=0;
        while(h<t){
            int now=q[++h];
            for(int i=head[now];i;i=e[i].pre){
                int v=e[i].v;
                if(e[i].f&&dis[v]>dis[now]+1){
                    dis[v]=dis[now]+1;
                    if(v==T)return true;
                    q[++t]=v;
                }
            }
        }
        return dis[T]!=inf;
    }
    int dinic(int now,int f){
        if(now==T)return f;
        int rest=f;
        for(int i=head[now];i;i=e[i].pre){
            int v=e[i].v;
            if(e[i].f&&dis[v]==dis[now]+1){
                int t=dinic(v,min(rest,e[i].f));
                if(!t)dis[v]=0;
                e[i].f-=t;
                e[i^1].f+=t;
                rest-=t;
            }
        }
        return f-rest;
    }
    int main(){
        freopen("grid.in","r",stdin);
        freopen("grid.out","w",stdout);
        scanf("%d%d",&n,&m);
        S=0;T=n*m+1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
                ans+=a[i][j];
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(i+j&1) add(ws(i,j),T,a[i][j]);
                else add(S,ws(i,j),a[i][j]);
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(i+j&1)continue;
                if(i-1>=1) add(ws(i,j),ws(i-1,j),inf);
                if(i+1<=n) add(ws(i,j),ws(i+1,j),inf);
                if(j-1>=1) add(ws(i,j),ws(i,j-1),inf);
                if(j+1<=m) add(ws(i,j),ws(i,j+1),inf);
            }
        while(bfs()) ans-=dinic(S,inf);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    中小企业发展环境十强
    asp.net发送邮件时报:无法从传输连接中读取数据: net_io_connectionclosed。
    .netCore学习一
    Python项目打包
    Linux中安装JMeter并执行压测
    用Python生成随机长度的字符串和随机长度的数字
    用Python将内容输出到文档的两种方式
    Python学习系列之项目打包成可执行exe文件(三十五)
    Python学习系列之Python中的包(三十一)
    Python学习系列之以主程序形式运行(三十)
  • 原文地址:https://www.cnblogs.com/harden/p/6261717.html
Copyright © 2020-2023  润新知