zoukankan      html  css  js  c++  java
  • Luogu_2774 方格取数问题

    Luogu_2774 方格取数问题

    二分图最小割

    第一次做这种题,对于某些强烈暗示性的条件并没有理解到。

    也就是每一立刻理解到是这个图是二分图。

    为什么?
    横纵坐标为奇数的只会和横纵坐标为偶数的相连。

    最大和=全局和-最小代价

    所以可以反向缩小最小代价。

    考虑奇数点与源点相连,偶数点与汇点相连,流量都是这个点的权值。

    然后奇数点像偶数点连边,权值无限大。

    这样构图。最小割是一个简单割。

    割的流量就是最小的代价。

    要么奇数点被割去,要么相邻的四个偶数点被割去

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    
    using std::queue;
    using std::min;
    
    const int maxn=301;
    const int inf=0x7fffffff;
    const int dx[]={0,0,1,-1};
    const int dy[]={1,-1,0,0};
    
    struct node
    {
        int p;
        int nxt;
        int value;
        node(int a=0,int b=0,int c=0)
        {
            p=a;
            value=b;
            nxt=c;
        }
    };
    
    node line[maxn*maxn<<1];
    int head[maxn*maxn],tail;
    int cur[maxn*maxn];
    int Dis[maxn*maxn];
    int Map[maxn][maxn];
    int S,T;
    
    void add(int a,int b,int c,int d)
    {
        line[++tail]=node(b,c,head[a]);
        head[a]=tail;
        line[++tail]=node(a,d,head[b]);
        head[b]=tail;
    }
    
    void init(int n,int m)
    {
        S=n*m;T=n*m+1;
        tail=-1;
        memset(head,-1,sizeof(head));
    }
    
    int Bfs(int s,int t)
    {
        queue<int>q;
        memset(Dis,0,sizeof(Dis));
        Dis[s]=1;q.push(s);
        while(!q.empty())
        {
            int pas=q.front();q.pop();
            for(int i=head[pas];i!=-1;i=line[i].nxt)
            {
                int v=line[i].p;
                if(Dis[v]||!line[i].value)  continue;
                Dis[v]=Dis[pas]+1;
                q.push(v);
            }
        }
        for(int i=0;i<=T;i++)   cur[i]=head[i];
        return Dis[t];
    }
    
    int Dfs(int now,int aim,int limte)
    {
        if(now==aim||!limte)    return limte;
        int res=0,f;
        for(int &i=cur[now];i!=-1;i=line[i].nxt)
        {
            int v=line[i].p;
            if(Dis[v]==Dis[now]+1&&(f=Dfs(v,aim,min(limte,line[i].value))))
            {
                res+=f;
                limte-=f;
                line[i].value-=f;
                line[i^1].value+=f;
                if(!limte)  break;
            }
        }
        return res;
    }
    
    int Dinic(int s,int t)
    {
        int res=0;
        while(Bfs(s,t))
            res+=Dfs(s,t,inf);
        return res;
    }
    
    int main()
    {
        int n,m,tot=0;
        scanf("%d%d",&n,&m);
        init(n,m);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                scanf("%d",&Map[i][j]);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                if(((i+j)&1)==1)
                {
                    add(S,i*m+j,Map[i][j],0);
                    for(int k=0;k<4;k++)
                        if(i+dx[k]>=0&&i+dx[k]<n&&j+dy[k]>=0&&j+dy[k]<m)
                            add(i*m+j,(i+dx[k])*m+(j+dy[k]),inf,0);
                }
                else
                    add(i*m+j,T,Map[i][j],0);
                tot+=Map[i][j];
            }
        printf("%d",tot-Dinic(S,T));
        return 0;
    }
    
    
  • 相关阅读:
    Insufficient parameters supplied to the command
    helloworld program of Linden Scripting Language
    使用DEV控件开发的小软件,单词查询及单词浏览
    SqlBulkCopy基本使用
    .NET3.0+中使软件发出声音[整理篇]
    Quick Hack for Setting the Row Height of a ListViewItem
    WCF返回JSON及EXT调用WCF
    拖动PictureBox 代码片断
    WCF配置工具及服务调试工具
    为指定的XML文件生成类并反序列化
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/10295246.html
Copyright © 2011-2022 走看看