P2774 方格取数问题 (最小割)

题目链接

 

 

 解法参见:https://www.luogu.com.cn/blog/cicos/solution-p2774#

 

Code:

  1 #include <bits/stdc++.h>
  2 #define LL long long
  3 #define INF 0x3f3f3f3f;
  4 using namespace std;
  5 
  6 int M, N;
  7 int S, T;
  8 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
  9 struct Edge{
 10     int next, from, to, remain;
 11 }e[30000];
 12 int en;
 13 int head[11000];
 14 queue<int> q;
 15 int visited[11000];
 16 int preEdge[11000];
 17 int minflow[11000];
 18 int resflow;
 19 int totalSum;
 20 
 21 void addEdge(int from, int to, int flow){
 22     e[en].next=head[from];
 23     e[en].from=from;
 24     e[en].to=to;
 25     e[en].remain=flow;
 26     head[from]=en;
 27     ++en;
 28 }
 29 
 30 void add(int from, int to, int flow){
 31     addEdge(from, to, flow);
 32     addEdge(to, from, 0);
 33 }
 34 
 35 void bfs(){
 36     memset(visited,0,sizeof(visited));
 37     memset(preEdge,-1,sizeof(preEdge));
 38     memset(minflow,0,sizeof(minflow));
 39     q.push(S);
 40     visited[S]=1;
 41     minflow[S]=INF;
 42     while(!q.empty()){
 43         int u=q.front();
 44         q.pop();
 45         for(int i=head[u];i!=-1;i=e[i].next){
 46             if(e[i].remain>0 && !visited[e[i].to]){
 47                 visited[e[i].to]=1;
 48                 minflow[e[i].to]=min(minflow[u],e[i].remain);
 49                 preEdge[e[i].to]=i;
 50                 q.push(e[i].to);
 51             }
 52         }
 53     }
 54 }
 55 
 56 void EK(){
 57     while(true){
 58         bfs();
 59         if(preEdge[T]==-1) break;
 60         resflow+=minflow[T];
 61         int v=T;
 62         while(true){
 63             int edge=preEdge[v];
 64             if(edge==-1) break;
 65             e[edge].remain-=minflow[T];
 66             e[edge^1].remain+=minflow[T];
 67             v=e[edge].from;
 68         }
 69     }
 70 }
 71 
 72 int getIndex(int i, int j){
 73     return i*N+j;
 74 }
 75 
 76 int main(){
 77     memset(head,-1,sizeof(head));
 78     scanf("%d %d", &M, &N);
 79     S=2*M*N, T=3*M*N;
 80     for(int i=0;i<M;++i){
 81         for(int j=0;j<N;++j){
 82             int num;
 83             scanf("%d", &num);
 84             totalSum+=num;
 85             if((i+j)%2==0){
 86                 add(S,getIndex(i,j),num);
 87             }else {
 88                 add(getIndex(i,j),T,num);
 89             }
 90         }
 91     }
 92     for(int i=0;i<M;++i){
 93         for(int j=0;j<N;++j){
 94             if((i+j)%2==0){
 95                 for(int d=0;d<4;++d){
 96                     int ni=i+dir[d][0];
 97                     int nj=j+dir[d][1];
 98                     if(ni>=0 && ni<M && nj>=0 && nj<N){
 99                         add(getIndex(i,j),getIndex(ni,nj),0x3f3f3f3f);
100                     }
101                 }
102             }
103         }
104     }
105 
106     EK();
107 
108     printf("%d", totalSum-resflow);
109     return 0;
110 }

 

posted @ 2020-01-31 16:25  feibilun  阅读(138)  评论(0编辑  收藏  举报