[网络流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;
}

 

posted @ 2018-08-23 13:42  NewErA  阅读(259)  评论(0编辑  收藏  举报