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;
    }
  • 相关阅读:
    668. Kth Smallest Number in Multiplication Table
    658. Find K Closest Elements
    483. Smallest Good Base
    475. Heaters
    454. 4Sum II
    441. Arranging Coins
    436. Find Right Interval
    410. Split Array Largest Sum
    392. Is Subsequence
    378. Kth Smallest Element in a Sorted Matrix
  • 原文地址:https://www.cnblogs.com/newera/p/9523272.html
Copyright © 2011-2022 走看看