zoukankan      html  css  js  c++  java
  • [网络流24题#9] [cogs734] 方格取数 [网络流,最大流最小割]

    将网格分为两部分,方法是黑白染色,即判断(i+j)&1即可,分开后从白色格子向黑色格子连边,每个点需要四条(边界点可能更少),也就是每个格子周围的四个方向。之后将源点和汇点分别于黑白格子连边,边权即为点权,最后用总权值减去最小割即可。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <queue>
    
    using namespace std;
    
    #define    INF    0x3f3f3f3f
    
    template<const int _n,const int _m>
    struct Edge
    {
        struct Edge_base { int    to,next,w; }e[_m]; int    cnt,p[_n];
        Edge() { clear(); }
        void    insert(const int x,const int y,const int z)
        { e[++cnt].to=y; e[cnt].next=p[x]; e[cnt].w=z; p[x]=cnt; return ; }
        int    start(const int x) { return p[x]; }
        void    clear() { cnt=1,memset(p,0,sizeof(p)); }
        Edge_base&    operator[](const int x) { return e[x]; }
    };
    
    int    n,m,N,SSS,TTT,a[410][410];
    int    level[41000],cur[41000];
    Edge<41000,410000>    e;
    
    bool    Bfs(const int S)
    {
        int    i,t;
        queue<int>    Q;
        memset(level,0,sizeof(level));
        level[S]=1;
        Q.push(S);
        while(!Q.empty())
        {
            t=Q.front(),Q.pop();
            for(i=e.start(t);i;i=e[i].next)
            {
                if(!level[e[i].to] && e[i].w)
                {
                    level[e[i].to]=level[t]+1;
                    Q.push(e[i].to);
                }
            }
        }
        return level[TTT];
    }
    
    int    Dfs(const int S,const int bk)
    {
        if(S==TTT)return bk;
        int    rest=bk;
        for(int &i=cur[S];i;i=e[i].next)
        {
            if(level[e[i].to]==level[S]+1 && e[i].w)
            {
                int    flow=Dfs(e[i].to,min(e[i].w,rest));
                e[i].w-=flow;
                e[i^1].w+=flow;
                if((rest-=flow)<=0)break;
            }
        }
        if(bk==rest)level[S]=0;
        return bk-rest;
    }
    
    int    Dinic()
    {
        int    flow=0;
        while(Bfs(SSS))
        {
            memcpy(cur,e.p,sizeof(cur));
            flow+=Dfs(SSS,0x3f3f3f3f);
        }
        return flow;
    }
    
    int main()
    {
        freopen("grid.in","r",stdin);
        freopen("grid.out","w",stdout);
    
        int    i,j,Sum=0;
    
        scanf("%d%d",&n,&m);
        N=n*m;SSS=N+1,TTT=SSS+1;
        for(i=1;i<=n;++i)for(j=1;j<=m;++j)
            scanf("%d",&a[i][j]),Sum+=a[i][j];
        for(i=1;i<=n;++i)
        {
            for(j=1;j<=m;++j)
            {
                int t=(i-1)*m+j;
                if(((i&1) && !(j&1)) || (!(i&1) && (j&1)))
                {
                    e.insert(SSS,t,a[i][j]);
                    e.insert(t,SSS,0);
                    if(i>1)e.insert(t,t-m,INF),e.insert(t-m,t,0);
                    if(i<n)e.insert(t,t+m,INF),e.insert(t+m,t,0);
                    if(j>1)e.insert(t,t-1,INF),e.insert(t-1,t,0);
                    if(j<m)e.insert(t,t+1,INF),e.insert(t+1,t,0);
                }
                else
                {
                    e.insert(t,TTT,a[i][j]);
                    e.insert(TTT,t,0);
                    if(i>1)e.insert(t-m,t,INF),e.insert(t,t-m,0);
                    if(i<n)e.insert(t+m,t,INF),e.insert(t,t+m,0);
                    if(j>1)e.insert(t-1,t,INF),e.insert(t,t-1,0);
                    if(j<m)e.insert(t+1,t,INF),e.insert(t,t+1,0);
                }
            }
        }
    
        printf("%d
    ",Sum-Dinic());
    
        return 0;
    }
  • 相关阅读:
    竞赛中遇到的英文单词集锦
    #复习 搜索与图论:排列数字、走迷宫~ 20.8.20起
    #容斥原理 20.9.10
    #sort :快速排序、第k个数 20.09.12
    #STL #unordered_map : C++11 unordered_map详细介绍
    Java 面试必备(字符串专题)
    JAVA面试必备题(垃圾回收专题)
    Collection框架的结构(面试重点)
    CSS 层级样式表
    window搭建mongodb副本集
  • 原文地址:https://www.cnblogs.com/Gster/p/4996899.html
Copyright © 2011-2022 走看看