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

    题面:

    传送门

    思路:

    相邻的点不能同时取,那么在这个图中,实际上分了两种格子,每种格子相互之间随便取

    那么就是二分图了

    把相邻的点之间连边,得到一个二分图,我们实际上就是要求这个图的带权最大独立集

    于是这道题转化为二分图问题,而二分图中最大独立集等于全集减去最小点覆盖,最小点覆盖等于这个图的最大匹配(都带权)

    那么用网络流做就好了

    将这个平面上的方格像国际象棋那样黑白染色

    源点连黑点,容量为黑点权值

    黑点连白点,容量为inf

    白点连汇点,容量为白点权值

    跑S-T最大流(即S-T最小割),用所有点的权值和减去最大流值,就得到了答案

    因为在这个建好的网络流图里面,最大流等于最小割等于最小点覆盖

    Code:

    建图比较丑,请见谅

     1     #include<iostream>
     2     #include<cstdio>
     3     #include<cstring>
     4     #include<algorithm>
     5     #define inf 0x7fffffff
     6     using namespace std;
     7     inline int read(){
     8         int re=0,flag=1;char ch=getchar();
     9         while(ch>'9'||ch<'0'){
    10             if(ch=='-') flag=-1;
    11             ch=getchar();
    12         }
    13         while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
    14         return re*flag;
    15     }
    16     inline int _min(int l,int r){return (l>r)?r:l;}
    17     const int dx[5]={0,-1,0,1,0},dy[5]={0,0,-1,0,1};
    18     int n,m,cnt=-1,ans,x[50][50],first[2500],dep[2500],cur[2500];
    19     struct edge{
    20         int to,next,w;
    21     }a[500010];
    22     inline void add(int u,int v,int w){
    23     //    cout<<"add "<<u<<ends<<v<<ends<<w<<endl;
    24         a[++cnt].to=v;a[cnt].next=first[u];first[u]=cnt;a[cnt].w=w;
    25         a[++cnt].to=u;a[cnt].next=first[v];first[v]=cnt;a[cnt].w=0;
    26     }
    27     inline bool bfs(int s,int t){
    28         int q[2500],head=0,tail=1,i,u,v;
    29         for(i=s;i<=t;i++) dep[i]=inf,cur[i]=first[i];
    30         q[0]=s;dep[s]=0;
    31         while(head<tail){
    32             u=q[head++];
    33     //        cout<<"bfs "<<u<<ends<<dep[u]<<ends<<head<<ends<<tail<<endl;
    34             for(i=first[u];~i;i=a[i].next){
    35                 v=a[i].to;
    36                 if(!a[i].w||dep[v]!=inf) continue;
    37     //            cout<<"to "<<v<<endl;
    38                 dep[v]=dep[u]+1;
    39                 q[tail++]=v;
    40             }
    41     //        system("pause");
    42         }
    43         return dep[t]!=inf;
    44     }
    45     int dfs(int u,int t,int low){
    46     //    cout<<"dfs "<<u<<ends<<t<<ends<<low<<endl;
    47         if(u==t||!low) return low;
    48         int flow=0,f,i,v;
    49         for(i=cur[u];~i;i=a[i].next){
    50             cur[u]=i;v=a[i].to;
    51             if(dep[v]==dep[u]+1&&(f=dfs(v,t,_min(low,a[i].w)))){
    52     //            cout<<"in "<<u<<" return from "<<v<<ends<<f<<endl;
    53                 flow+=f;low-=f;
    54                 a[i].w-=f;a[i^1].w+=f;
    55                 if(!low) break;
    56             }
    57         }
    58     //    cout<<"return "<<u<<ends<<t<<ends<<low<<ends<<flow<<endl;
    59         return flow;
    60     }
    61     void dinic(){
    62         while(bfs(0,n*m+1)) ans+=dfs(0,n*m+1,inf);
    63     }
    64     int main(){
    65         freopen("grid.in","r",stdin);
    66         freopen("grid.out","w",stdout);
    67         memset(first,-1,sizeof(first));
    68         int i,j,k,ti,tj;
    69         n=read();m=read();
    70         for(i=1;i<=n;i++) for(j=1;j<=m;j++) x[i][j]=read(),ans-=x[i][j];
    71         for(i=1;i<=n;i++){
    72             for(j=1;j<=m;j++){
    73                 if((i+j)&1) add((i-1)*m+j,n*m+1,x[i][j]);
    74                 else add(0,(i-1)*m+j,x[i][j]);
    75                 if((i+j)&1) continue;
    76                 for(k=1;k<=4;k++){
    77                     ti=i+dx[k];tj=j+dy[k];
    78                     if(ti<1||ti>n||tj<1||tj>m) continue;
    79                     add((i-1)*m+j,(ti-1)*m+tj,inf);
    80                 }
    81             }
    82         }
    83         dinic();
    84         printf("%d",-ans);
    85     }
  • 相关阅读:
    Python——学习笔记
    Ubuntu开发相关环境搭建
    解决联想R720双系统Ubuntu16.04的无线网卡开启问题及信号不稳定
    Win10环境下多JDK切换以及could not find java.dll异常解决
    Java——this关键字总结
    Java——多线程编程学习/01
    Python日常Bug集
    《集体智慧编程学习笔记》——Chapter2:提供推荐
    解决Pycharm无法显示matplotlib绘图问题
    Kettle启动时报错Cannot create java virtual machine & A java exception has occurred
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8454337.html
Copyright © 2011-2022 走看看