AC日记——[网络流24题]方格取数问题 cogs 734

734. [网络流24题] 方格取数问题

★★☆   输入文件:grid.in   输出文件:grid.out   简单对比
时间限制:1 s   内存限制:128 MB

«问题描述:
在一个有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)

思路:

  取数;

  取出的数满足任意两两坐标不相邻;

  所以,我们把点标记;

  把全部的点都用bfs标记成true或者false;

  true与true不相邻,false与false不相邻;

  然后标记为true的点在集合a;

  标记为false的点在集合b;

  建立超级源点s和超级汇点t;

  s向a的每个点连边,流量为点的权值;

  t向b的每个点连边,流量为点的权值;

  然后,a中与b相邻的点连边,流量无限大;

  然后求出最小割;

  最后的ans等于所有点权值的总和减去最小割;

来,上代码:

#include <queue>
#include <cstdio>
#include <iostream>

using namespace std;

struct ColorNode {
    int x,y;
    bool color;
};

struct EdgeType {
    int v,f,e;
};
struct EdgeType edge[900000];

const int dx[5]={0,-1,0,1,0};
const int dy[5]={0,0,1,0,-1};

int n,m,dis[50][50],ans,head[1001],s=0,t;
int cnt=1,deep[1001];

bool if_[50][50];

char Cget;

inline void in(int &now)
{
    now=0,Cget=getchar();
    while(Cget>'9'||Cget<'0') Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}

struct ColorNode node(int x,int y,int color)
{
    struct ColorNode pos;
    pos.x=x,pos.y=y,pos.color=color;
    return pos;
}

inline void edge_add(int u,int v,int f)
{
    edge[++cnt].v=v,edge[cnt].f=f,edge[cnt].e=head[u],head[u]=cnt;
    edge[++cnt].v=u,edge[cnt].f=0,edge[cnt].e=head[v],head[v]=cnt;
}

bool BFS()
{
    queue<int>que;
    for(int i=s;i<=t;i++) deep[i]=-1;
    deep[s]=0;que.push(s);
    while(!que.empty())
    {
        int pos=que.front();que.pop();
        for(int i=head[pos];i;i=edge[i].e)
        {
            if(deep[edge[i].v]<0&&edge[i].f>0)
            {
                deep[edge[i].v]=deep[pos]+1;
                if(edge[i].v==t) return true;
                que.push(edge[i].v);
            }
        }
    }
    return false;
}

int flowing(int now,int flow)
{
    if(now==t||flow<=0) return flow;
    int oldflow=0;
    for(int i=head[now];i;i=edge[i].e)
    {
        if(edge[i].f<=0||deep[edge[i].v]!=deep[now]+1) continue;
        int pos=flowing(edge[i].v,min(edge[i].f,flow));
        flow-=pos;
        oldflow+=pos;
        edge[i].f-=pos;
        edge[i^1].f+=pos;
        if(flow==0) return oldflow;
    }
    return oldflow;
}

int main()
{
    freopen("grid.in","r",stdin);
    freopen("grid.out","w",stdout);
    in(n),in(m);t=n*m+1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            in(dis[i][j]);
            ans+=dis[i][j];
        }
    }
    queue<ColorNode>que;
    if_[1][1]=true;
    que.push(node(1,1,if_[1][1]));
    while(!que.empty())
    {
        struct ColorNode pos=que.front();que.pop();
        if(pos.color)
        {
            edge_add(s,(pos.x-1)*m+pos.y,dis[pos.x][pos.y]);
            int x=pos.x,y=pos.y,hash=(pos.x-1)*m+pos.y;
            for(int i=1;i<=4;i++)
            {
                if(x+dx[i]>0&&x+dx[i]<=n&&y+dy[i]>0&&y+dy[i]<=m)
                {
                    edge_add(hash,(pos.x+dx[i]-1)*m+pos.y+dy[i],0x7ffffff);
                }
            }
        }
        else edge_add((pos.x-1)*m+pos.y,t,dis[pos.x][pos.y]);
        if(pos.x+1<=n&&!if_[pos.x+1][pos.y])
        {
            que.push(node(pos.x+1,pos.y,!pos.color));
            if_[pos.x+1][pos.y]=true;
        }
        if(pos.y+1<=m&&!if_[pos.x][pos.y+1])
        {
            if_[pos.x][pos.y+1]=true;
            que.push(node(pos.x,pos.y+1,!pos.color));
        }
    }
    while(BFS()) ans-=flowing(s,0x7ffffff);
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6501690.html