zoukankan      html  css  js  c++  java
  • [网络流24题]方格取数

    Link:

    P2774 传送门

    Solution:

    方格取数和最大且要求两两没有公共边

    遇到方格内的不相邻问题,考虑黑白染色来对点分类

    问题转化为使黑点不和白点相邻的最小代价,其中每个点的代价只计算一次

    明显的集合划分模型,用最小割解决:

    $<S,black,w>,<white,T,w>,<blakc,white,INF>$

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1e5+10,INF=1<<30;
    int n,m,dat[105][105],sum;
    namespace Maxflow
    {
        struct edge{int nxt,to,cap;}e[MAXN<<2];
        int S,T,head[MAXN],iter[MAXN],dist[MAXN],tot=-1;
        void add_edge(int from,int to,int cap)
        {
            e[++tot].nxt=head[from];e[tot].to=to;e[tot].cap=cap;head[from]=tot;
            e[++tot].nxt=head[to];e[tot].to=from;e[tot].cap=0;head[to]=tot;
        }
        
        bool bfs()
        {
            memset(dist,-1,sizeof(dist));
            queue<int> q;q.push(S);dist[S]=0;
            while(!q.empty())
            {
                int v=q.front();q.pop();
                for(int i=head[v];i!=-1;i=e[i].nxt)
                {
                    if(e[i].cap&&dist[e[i].to]==-1)
                        dist[e[i].to]=dist[v]+1,q.push(e[i].to);
                }
            }
            return dist[T]!=-1;
        }
        
        int dfs(int v,int f)
        {
            if(v==T) return f;
            int ret=0;
            for(int &i=iter[v];i!=-1;i=e[i].nxt)
                if(dist[e[i].to]==dist[v]+1&&e[i].cap)
                {
                    int d=dfs(e[i].to,min(f,e[i].cap));
                    e[i].cap-=d;e[i^1].cap+=d;
                    f-=d;ret+=d;if(!f) break;
                }
            return ret;
        }
        
        int Dinic()
        {
            int ret=0;
            while(bfs())
            {
                for(int i=0;i<MAXN;i++) iter[i]=head[i];
                ret+=dfs(S,INF);
            }
            return ret;
        }
    }
    using namespace Maxflow;
    int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
    int idx(int x,int y){return (x-1)*m+y;}
    
    int main()
    {
        scanf("%d%d",&n,&m);
        S=0;T=n*m+1;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&dat[i][j]),sum+=dat[i][j];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if((i+j)%2==1) add_edge(idx(i,j),T,dat[i][j]);
                else
                {
                    add_edge(S,idx(i,j),dat[i][j]);
                    for(int k=0;k<4;k++)
                    {
                        int fx=i+dx[k],fy=j+dy[k];
                        if(fx<1||fx>n||fy<1||fy>m) continue;
                        add_edge(idx(i,j),idx(fx,fy),INF);
                    }
                }
        printf("%d",sum-Dinic());
        return 0;
    }
  • 相关阅读:
    IIS7.x经典模式与集成模式
    pocketsphinx实现连续大词汇量语音识别
    js对象冒充实现的继承
    你不得不知道的HTML5的新型标签
    (译)开发优秀的虚拟现实体验:从开发I Expect You to Die中总结的六个要点
    《构建之法》阅读梳理篇读后感
    VR介绍
    推荐
    VR设备
    开发VR游戏的基本要求
  • 原文地址:https://www.cnblogs.com/newera/p/9523272.html
Copyright © 2011-2022 走看看