【bzoj3894】文理分科 网路流

【bzoj3894】文理分科

Description

 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠
结过)
 小P所在的班级要进行文理分科。他的班级可以用一个n*m的矩阵进行
描述,每个格子代表一个同学的座位。每位同学必须从文科和理科中选择
一科。同学们在选择科目的时候会获得一个满意值。满意值按如下的方式
得到:
1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如
  果选择理科,将得到science[i][j]的满意值。
2.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻当且
  仅当它们拥有一条相同的边)的同学全部选择了文科,则他会更开
  心,所以会增加same_art[i][j]的满意值。
3.如果第i行第j列的同学选择了理科,并且他相邻的同学全部选择了理
  科,则增加same_science[i]j[]的满意值。
  小P想知道,大家应该如何选择,才能使所有人的满意值之和最大。请
告诉他这个最大值。

Input

第一行为两个正整数:n,m
接下来n术m个整数,表示art[i][j];
接下来n术m个整数.表示science[i][j];
接下来n术m个整数,表示same_art[i][j];

Output

输出为一个整数,表示最大的满意值之和

Sample Input

3 4
13 2 4 13
7 13 8 12
18 17 0 58 13 15 4
11 3 8 11
11 18 6 51 2 3 4
4 2 3 2
3 1 0 4

3 2 3 2
0 2 2 1
0 2 4 4

Sample Output

152

HINT

样例说明
1表示选择文科,0表示选择理科,方案如下:
1  0  0  1
0  1  0  0
1  0  0  0
N,M<=100,读入数据均<=500
 
  1 #include<cstring>
  2 #include<cmath>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cstdio>
  6 #include<queue>
  7 
  8 #define inf 1000000007
  9 #define N 30007
 10 #define M 1000007
 11 using namespace std;
 12 const int xx[5]={0,1,-1,0,0};
 13 const int yy[5]={0,0,0,1,-1};
 14 inline int read()
 15 {
 16     int x=0,f=1;char ch=getchar();
 17     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
 18     while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
 19     return x*f;
 20 }
 21 
 22 int n,m,S,T,ans;
 23 int cnt=1,hed[N],cur[N],nxt[M],rea[M],val[M];
 24 int dis[N];
 25 
 26 void add(int u,int v,int w)
 27 {
 28     nxt[++cnt]=hed[u];
 29     hed[u]=cnt;
 30     rea[cnt]=v;
 31     val[cnt]=w;
 32 }
 33 void add_two_edge(int u,int v,int w)
 34 {
 35     add(u,v,w),add(v,u,0);
 36 }
 37 bool bfs()
 38 {
 39     for (int i=S;i<=T;i++)dis[i]=-1;
 40     dis[S]=0;queue<int>q;q.push(S);
 41     while(!q.empty())
 42     {
 43         int u=q.front();q.pop();
 44         for (int i=hed[u];i!=-1;i=nxt[i])
 45         {
 46             int v=rea[i],fee=val[i];
 47             if (dis[v]!=-1||fee==0)continue;
 48             dis[v]=dis[u]+1;
 49             if (v==T)return 1;
 50             q.push(v);
 51         }
 52     }
 53     return 0;
 54 }
 55 int dfs(int u,int MX)
 56 {
 57     if (u==T||MX==0) return MX;
 58     int res=0;
 59     for (int i=cur[u];i!=-1;i=nxt[i])
 60     {
 61         int v=rea[i],fee=val[i];
 62         if (dis[v]!=dis[u]+1)continue;
 63         int x=dfs(v,min(MX,fee));
 64         cur[u]=i,res+=x,MX-=x;
 65         val[i]-=x,val[i^1]+=x;
 66         if (!MX)break;
 67     }
 68     if (!res) dis[u]=-1;
 69     return res;
 70 }
 71 int dinic()
 72 {
 73     int res=0;
 74     while(bfs())
 75     {
 76     //    cout<<1<<endl;
 77         for (int i=S;i<=T;i++)cur[i]=hed[i];
 78         res+=dfs(S,inf);
 79     }
 80     return res;
 81 }
 82 int main()
 83 {
 84     memset(hed,-1,sizeof(hed));
 85     n=read(),m=read(),S=0,T=n*m*3+1;
 86     for (int i=1;i<=n;i++)
 87         for (int j=1;j<=m;j++)
 88         {
 89             int x=read();ans+=x;
 90             add_two_edge(S,(i-1)*m+j,x);
 91         }
 92     for (int i=1;i<=n;i++)
 93         for (int j=1;j<=m;j++)
 94         {
 95             int x=read();ans+=x;
 96             add_two_edge((i-1)*m+j,T,x);
 97         }
 98     for (int i=1;i<=n;i++)
 99         for (int j=1;j<=m;j++)
100         {
101             int x=read();ans+=x;
102             for (int k=0;k<5;k++)
103             {
104                 int lx=i+xx[k],ly=j+yy[k];
105                 if (lx<1||lx>n||ly<1||ly>m)continue;
106                 add_two_edge((i-1)*m+j+n*m,(lx-1)*m+ly,inf);
107             }
108             add_two_edge(S,(i-1)*m+j+n*m,x);
109         }
110     for (int i=1;i<=n;i++)
111         for (int j=1;j<=m;j++)
112         {
113             int x=read();ans+=x;
114             for (int k=0;k<5;k++)
115             {
116                 int lx=i+xx[k],ly=j+yy[k];
117                 if (lx<1||lx>n||ly<1||ly>m)continue;
118                 add_two_edge((lx-1)*m+ly,(i-1)*m+j+2*n*m,inf);
119             }
120             add_two_edge((i-1)*m+j+2*n*m,T,x);
121         }
122     ans-=dinic();
123     printf("%d
",ans);
124 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8287313.html