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;
    }
    
  • 相关阅读:
    PNG文件格式具体解释
    opencv2对读书笔记——使用均值漂移算法查找物体
    Jackson的Json转换
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 单词接龙
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998798.html
Copyright © 2011-2022 走看看