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 5

8 13 15 4
11 3 8 11
11 18 6 5

1 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
感觉题目描述有点问题
不看题解根本不知道怎么建图。
分析:首先如果没有相邻全选情况,建图比较容易。文科与S相连,理科与T相连,求最小割,每条路径必定割掉一条边。
下面考虑相邻全选情况。相邻中有任意一人选文,就没有额外的理科加成。同理相邻任意一人选理,就没有额外的文科加成。根据这个可以这样建图,每个点再拆为P1,P2,如图:
1,2,3,4为某个位置的相邻点。与P1相连,流量为inf,这样如果任意一个选文科(假设a[1]),即与S相连,必定会割掉Same_s这条边。因为选a[1],肯定没有s[1],要保持不连通,最小割肯定割Same_s,不会割inf。同理对于Same_a,也一样。任意一个选理科(假设s[3]),与T相连,肯定没有a[3],要保持不连通,最小割肯定割Same_a,不会割inf。
这样建图满足了额外加成的控制。
直接用总的满意度-最小割即可
第一次知道拆点方法,P(i,j) = (i-1)*m+j,然后P1=P(i,j)+n*m  P2=P(i,j)+2*n*m
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define P(i,j) (i-1)*m+j
  4
  5 const int maxn=100010;
  6 const int maxm=400010;
  7 const int inf=0x3f3f3f3f;
  8 struct Edge{
  9     int to,next,cap,flow,cost;
 10 }edge[maxm];
 11
 12 int tol;
 13 int head[maxn];
 14 int gap[maxn],dep[maxn],cur[maxn];
 15 int dir[][2]={0,0,1,0,-1,0,0,-1,0,1};
 16 void init() {
 17     tol=0;
 18     memset(head,-1,sizeof(head));
 19 }
 20 void addedge(int u,int v,int w,int rw=0) {
 21     edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
 22     edge[tol].next=head[u];head[u]=tol++;
 23     edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
 24     edge[tol].next=head[v];head[v]=tol++;
 25 }
 26
 27 int Q[maxn];
 28 void bfs(int start,int end) {
 29     memset(dep,-1,sizeof(dep));
 30     memset(gap,0,sizeof(gap));
 31     gap[0]=1;
 32     int front=0,rear=0;
 33     dep[end]=0;
 34     Q[rear++]=end;
 35     while(front!=rear) {
 36         int u=Q[front++];
 37         for(int i=head[u];i!=-1;i=edge[i].next) {
 38             int v=edge[i].to;
 39             if(dep[v]!=-1) continue;
 40             Q[rear++]=v;
 41             dep[v]=dep[u]+1;
 42             gap[dep[v]]++;
 43         }
 44     }
 45 }
 46
 47 int S[maxn];
 48 int sap(int start,int end,int n) {
 49     bfs(start,end);
 50     memcpy(cur,head,sizeof(head));
 51     int top=0;
 52     int u=start;
 53     int ans=0;
 54     while(dep[start]<n) {
 55         if(u==end) {
 56             int minn=inf;
 57             int inser;
 58             for(int i=0;i<top;i++) {
 59                 if(minn>edge[S[i]].cap-edge[S[i]].flow) {
 60                     minn=edge[S[i]].cap-edge[S[i]].flow;
 61                     inser=i;
 62                 }
 63             }
 64             for(int i=0;i<top;i++) {
 65                 edge[S[i]].flow+=minn;
 66                 edge[S[i]^1].flow-=minn;
 67             }
 68             ans+=minn;
 69             top=inser;
 70             u=edge[S[top]^1].to;
 71             continue;
 72         }
 73         bool flag=false;
 74         int v;
 75         for(int i=cur[u];i!=-1;i=edge[i].next) {
 76             v=edge[i].to;
 77             if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]) {
 78                 flag=true;
 79                 cur[u]=i;
 80                 break;
 81             }
 82         }
 83         if(flag) {
 84             S[top++]=cur[u];
 85             u=v;
 86             continue;
 87         }
 88         int minn=n;
 89         for(int i=head[u];i!=-1;i=edge[i].next) {
 90             if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<minn) {
 91                 minn=dep[edge[i].to];
 92                 cur[u]=i;
 93             }
 94         }
 95         gap[dep[u]]--;
 96         if(!gap[dep[u]]) return ans;
 97         dep[u]=minn+1;
 98         gap[dep[u]]++;
 99         if(u!=start) u=edge[S[--top]^1].to;
100     }
101     return ans;
102 }
103
104 int main() {
105     int n,m,x,sum;
106     while(~scanf("%d%d",&n,&m)) {
107         init();
108         sum=0;
109         int S=0,T=3*n*m+1;
110         for(int i=1;i<=n;i++) {
111             for(int j=1;j<=m;j++) {
112                 scanf("%d",&x);
113                 sum+=x;
114                 addedge(S,P(i,j),x);
115             }
116         }
117         for(int i=1;i<=n;i++) {
118             for(int j=1;j<=m;j++) {
119                 scanf("%d",&x);
120                 sum+=x;
121                 addedge(P(i,j),T,x);
122             }
123         }
124         for(int i=1;i<=n;i++) {
125             for(int j=1;j<=m;j++) {
126                 scanf("%d",&x);
127                 sum+=x;
128                 for(int k=0;k<5;k++) {
129                     int newx=i+dir[k][0];
130                     int newy=j+dir[k][1];
131                     if(newx<1||newx>n||newy<1||newy>m) continue;
132                     addedge(P(i,j)+2*n*m,P(newx,newy),inf);
133                 }
134                 addedge(S,P(i,j)+2*n*m,x);
135             }
136         }
137         for(int i=1;i<=n;i++) {
138             for(int j=1;j<=m;j++) {
139                 scanf("%d",&x);
140                 sum+=x;
141                 for(int k=0;k<5;k++) {
142                     int newx=i+dir[k][0];
143                     int newy=j+dir[k][1];
144                     if(newx<1||newx>n||newy<1||newy>m) continue;
145                     addedge(P(newx,newy),P(i,j)+n*m,inf);
146                 }
147                 addedge(P(i,j)+n*m,T,x);
148             }
149         }
150         printf("%d\n",sum-sap(0,T,T+1));
151     }
152 }

posted @ 2019-05-02 22:22 ACMerszl 阅读(...) 评论(...) 编辑 收藏

BZOJ3894 文理分科相关推荐

  1. BZOJ3894: 文理分科

    BZOJ3894: 文理分科 Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科. 他的班级可以用一个n*m的矩阵进行描述,每个 ...

  2. LuoguP4313 BZOJ3894 文理分科——最小割

    洛谷:文理分科 传送门 题目描述: 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行描述,每个格子代表一个同学的座位.每位同学必须从文科和理科中选择一科.同学们在选择科目的时候会获得一 ...

  3. bzoj3894 文理分科 最小割

    Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位 ...

  4. BZOJ3894:文理分科

    https://blog.csdn.net/PoPoQQQ/article/details/43968017 求最大收益->总收益-最小的丢失->最小割. 对于直接选文理很简单,直接把点分 ...

  5. BZOJ3894:文理分科——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3894 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理 ...

  6. [BZOJ 3894]文理分科(最小割)

    Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同 ...

  7. 文理分科 (最小割问题)

    Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行描述,每个格子代表一个同学的座位.每位同学 ...

  8. P4313 文理分科 详细理解

    P4313 文理分科 网络其他地方看到的原话:在说这道题之前,让我们先思考一下最小割的性质.最小割就是使得s到t割掉的最小边的容量,割过之后,所有的点要么与s联通,要么与t联通. 这样的性质,即要么与 ...

  9. luoguP4313 文理分科

    luoguP4313 文理分科 复习完之后做了道典型题目. 这道题条件有点多 我们逐个分析 如果没有\(sameart\)或者\(samescience\)的限制,就是一个裸的最大权闭合子图的问题了 ...

最新文章

  1. PPF(Point Pair Features)原理及实战技巧
  2. python正则表达式中的转义字符_详解python中正则表达式的反斜线的转义功能
  3. mvc:interceptor 不起作用的一个解决方法
  4. libsvm 训练后,模型参数详解
  5. 2 Effect Hook
  6. 扎心了,程序员2017到2019经历了什么?
  7. android 怎么刷机,android系统怎么刷机
  8. telerik:RadTreeView树形菜单鼠标放上去展开菜单
  9. 回顾一年的工作历程_ppt模板开门红年会颁奖典礼PPT模板,回顾总结过去一年的各项工作...
  10. 沙迦美国大学科研副校长赵伟:揭秘工业 4.0 核心技术 CPS 的前世今生 | 人物志...
  11. 最火的编程语言和开源项目,跟你想的一样吗?
  12. 图:昌荣传播2010夏令营拉歌大赛胜利闭幕
  13. Go gorilla websocket 小试牛刀
  14. LINUX系统使用锐捷客户端认证校园网(华中科技大学)
  15. lisp型材库_基于Auto LISP 创建V 带轮标准件库
  16. python ndarray append_Python中的numpy.append()
  17. Centos6、Centos7、Centos8关闭防火墙
  18. The resource identified by this request is only capable of generating respon
  19. 读书笔记:云计算概念、技术和架构
  20. 计算机化系统验证管理 360,欧盟发布2018版《计算机化系统验证指南》

热门文章

  1. Noip2011 Day1 T1 铺地毯(模拟)
  2. python判断字符串间的包含关系
  3. Linux进阶 | Docker部署nginx的web服务,VOLUME的使用详解,实现数据持久化!
  4. 信号采样与sinc插值恢复MATLAB
  5. Word 标题前添加一颜色竖线条
  6. 7、C语言回调函数使用
  7. 直播、网红和社交网络的Social Media化
  8. 计算机房屋出租系统毕业设计选题意义的说明
  9. 台式计算机怎么加一个硬盘,台式电脑增加硬盘_台式电脑增加硬盘图解
  10. 初入编程 - HTML + CSS