zoukankan      html  css  js  c++  java
  • 【24题】方格取数问题【网络流】

    题目大意:

    在一个有 n×mn\times m 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。


    思路:

    这道题明显是一个二分图。我们可以把每个点染色,将i+ji+j为偶数的点连向tt,否则连向ss。那么对于每一个连ss的白点,将它连向它周围的四个黑点,容量为INFINF。跑一边最大流即可。


    代码:

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <cstring>
    #define Inf 0x7f
    #define INF 1e9
    using namespace std;
    
    int n,m,s,t,x,y,k,head[200001],dep[200001],ans,sum,num;
    
    struct edge
    {
        int next,to,c;
    }e[200001];
    
    void add(int from,int to,int c)
    {
        k++;
        e[k].to=to;
        e[k].c=c;
        e[k].next=head[from];
        head[from]=k;
    }
    
    bool bfs()
    {
        memset(dep,Inf,sizeof(dep));
        dep[s]=0;
        queue<int> q;
        q.push(s);
        while (q.size())
        {
            int u=q.front();
            q.pop();
            for (int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if (dep[v]>dep[u]+1&&e[i].c)
                {
                    dep[v]=dep[u]+1;
                    q.push(v);
                }
            }
        }
        return dep[t]<Inf;
    }
    
    int dfs(int u,int low)
    {
        int lows=0;
        if (u==t) return low;
        for (int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if (dep[v]==dep[u]+1&&e[i].c)
            {
                lows=dfs(v,min(e[i].c,low));
                if (lows)
                {
                    e[i].c-=lows;
                    e[i^1].c+=lows;
                    return lows;
                }
            }
        }
        return 0;
    }
    
      //以上为最大流模板
    
    int main()
    {
        scanf("%d%d",&n,&m);
        k=1;
        s=n*m+4;
        t=n*m+5;
        for (int i=1;i<=n;i++)
         for (int j=1;j<=m;j++)
         {
         	scanf("%d",&x);
         	num+=x;
         	y=i*m-m+j;
         	if (!((i+j)%2))  //黑点
         	{
         		add(y,t,x);
         		add(t,y,0);
         	}
         	else  //白点
         	{
         		add(s,y,x);
         		add(y,s,0);
         		if (i>1)  //连上面的黑点
         		{
         			add(y,y-m,INF);
         			add(y-m,y,0);
         		}
         		if (i<n)  //连下面的黑点
         		{
         			add(y,y+m,INF);
         			add(y+m,y,0);
         		}
         		if (j>1)  //连左边的黑点
         		{
         			add(y,y-1,INF);
         			add(y-1,y,0);
         		}
         		if (j<m)  //连右边的黑点
         		{
         			add(y,y+1,INF);
         			add(y+1,y,0);
         		}
         	}
         }
         
        while (bfs())
        {
            while (sum=dfs(s,INF+1))
             ans+=sum;
        }
        printf("%d\n",num-ans);
        return 0;
    }
    
  • 相关阅读:
    枚举与常量需要注意的一个问题
    parted分区用法
    Linux下常用服务的端口号
    NFS服务
    mount用法
    Rsync服务部署
    常见的RAID级别
    SQL注入语句 (很全)
    数据库被注入daxia123或cn.jxmmtv.com原因及解决办法
    StringTemplate.net模板技术用法
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998797.html
Copyright © 2011-2022 走看看