• p2774 方格取数问题


    传送门

    分析

    我们只要求出拿出权值和最小的点集是的剩下的点合法即可

    求这个我们可以考虑最小割

    我们将棋盘黑白染色

    起点向黑点,白点向终点连边权为点权的边

    黑点向白点连边权为inf的边

    之后跑最小割即可

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<ctime>
    #include<queue>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    const int dx[] = {1,-1,0,0};
    const int dy[] = {0,0,1,-1};
    const int inf = 1e9+7;
    int n,m,s,t,head[2000100],to[2000100],nxt[2000100],w[2000100],ano[2000100],cnt,level[2000100],cur[2000100];
    inline void add(int x,int y,int z){
        nxt[++cnt]=head[x];
        head[x]=cnt;
        to[cnt]=y;
        w[cnt]=z;
        ano[cnt]=cnt+1;
        nxt[++cnt]=head[y];
        head[y]=cnt;
        to[cnt]=x;
        w[cnt]=0;
        ano[cnt]=cnt-1;
    }
    inline int id(int x,int y){return (x-1)*m+y;}
    inline void go(int x,int y){
        for(int i=0;i<4;i++){
          if(dx[i]+x<=0||dx[i]+x>n||dy[i]+y<=0||dy[i]+y>m)continue;
          add(id(x,y),id(dx[i]+x,dy[i]+y),inf);
        }
    }
    inline bool bfs(){
        memset(level,-1,sizeof(level));
        queue<int>q;
        level[s]=0;
        q.push(s);
        while(!q.empty()){
          int x=q.front();
          q.pop();
          for(int i=head[x];i;i=nxt[i])
            if(level[to[i]]==-1&&w[i]){
              level[to[i]]=level[x]+1;
              if(to[i]==t)return 1;
              q.push(to[i]);
            }
        }
        return 0;
    }
    inline int dfs(int x,int flow){
        if(x==t||!flow)return flow;
        int res=0;
        cur[x]=head[x];
        for(int i=cur[x];i;i=nxt[i]){
          cur[x]=i;
          if(level[to[i]]==level[x]+1&&w[i]){
              int f=dfs(to[i],min(w[i],flow-res));
              w[i]-=f;
              res+=f;
              w[ano[i]]+=f;
          }
        }
        if(!res)level[x]=-1;
        return res;
    }
    int main(){
        int i,j,k,Ans=0,tot=0;
        scanf("%d%d",&n,&m);
        s=n*m+1,t=s+1;
        for(i=1;i<=n;i++)
          for(j=1;j<=m;j++){
            scanf("%d",&k);
            if((i+j)&1)add(s,id(i,j),k);
              else add(id(i,j),t,k);
            if((i+j)&1)go(i,j);
            tot+=k;
          }
        while(bfs())while(int a=dfs(s,inf))Ans+=a;
        cout<<tot-Ans;
        return 0;
    }
  • 相关阅读:
    _1_html_框架
    _0_web_基础
    _0_工具
    虚拟机安装与使用
    NumPy数据类型
    NumPy Ndarray对象
    机器学习之K-近邻(KNN)算法
    vue项目如何打包扔向服务器
    Eslint 规则说明
    Python ssh 远程执行shell命令
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10527216.html
Copyright © 2020-2023  润新知