【BZOJ2127】happiness
Time Limit: 1000 ms Memory Limit: 256 MB
Description
高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。
Input
第一行两个正整数n,m。接下来是六个矩阵第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。
Output
输出一个整数,表示喜悦值总和的最大值
Sample Input
1 1
100 110
1
1000
Sample Output
【样例说明】
两人都选理,则获得100+110+1000的喜悦值。
【数据规模】
对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数
Solution
这种相邻格子的问题,一般都是考虑两个相邻的格子的最小割模型,然后把所有模型叠加起来。
现在考虑相邻的两人$x$和$y$。$x$选文或理的收益是$x_0,x_1$;$y$选文或理的收益是$y_0,y_1$;都选文的收益是$s_0$,都选理的收益是$s_1$。
那么从总收益$sum=x_0+x_1+y_0+y_1+s_0+s_1$中减去最小割就是最优解。
考虑一下逻辑关系:
(1)如果$x$和$y$都选文,那么需要割去$x_1,y_1,s_1$
(2)如果$x$和$y$都选理,那么需要割去$x_0,y_0,s_0$
(3)如果$x$文$y$理,那么需要割去$x_1,y_0,s_0,s_1$
(4)如果$x$理$y$文,那么需要割去$x_0,y_1,s_0,s_1$
发现一个人选一科,必定割掉另外一科的喜悦值。那么由源点$S$向$x$连$x_0$的边,向$y$连$y_0$的边;$x$向汇点$T$连$x_1$的边,向$y$连$y_1$的边。
现在,(1)和(2)还差$s_0$和$s_1$未刻画。因为割掉两条边以后貌似图就彻底分开了,不好再加入新的边来体现,我们考虑将$s_0$附加在$x_0$与$y_0$上,将$s_1$附加在$x_1$与$y_1$上,即各分一半:
(1)和(2)刻画完毕。但是(3)和(4)在其中不适用了。
如果$x$选文,$y$选理,那么割去的边是右上和左下两条边,其权值之和是$x_1+\frac{1}{2}s_1+y_0+\frac{1}{2}s_0$,但是我们期望的是$x_1+y_0+s_0+s_1$,不对啊。
怎么办?期望值和当前值一作差,得$\frac{1}{2}s_0+\frac{1}{2}s_1=\frac{1}{2}(s_0+s_1)$。想办法把它实例化!当割去的是右上和左下两条边时,已经形成最小割,那么强行把这条边塞进去!由$y$向$x$连一条权值为$\frac{1}{2}(s_0+s_1)$的调整边即可。
$x$理$y$文同理。
中间的两条调整边,仅在二者文理不同的时候起作用。现在这个模型,已经可以刻画(1)~(4)所有的情况了。
对全图进行建模,跑出最小割,用总收益和减去最小割即可。
Important:
我们不能对于每两个格子都像如上模型一样连接$(S,x),(S,y),(x,T),(y,T)$,将总收益和看做每两个格子的$sum$之和,然后将模型并起来跑。
为什么?因为这样我们会发现某一些$x_0$、$x_1$和$y_0$、$y_1$被多算了几次,这是极不好的,模型之间出现了交集。
事实上对于一个点$x$,我们将所有$S$->$x$的边都合并起来:即权值应该为:$x_0$或$y_0$加上$\frac{1}{2} \sum s_0$。$x$到$T$的边同理。
而中间的调整边照常即可。
这样当$sum$为所有格子的收益和的时候,用$sum$减去最小割的答案是对的。
Tips:
可以将边权乘上2,跑出最小割后除以2,即可忽略小数。
#include <cstdio>
#include <queue>
using namespace std;
const int N=,INF=;
int n,m,a[][],b[][],ax[][],ay[][],bx[][],by[][];
int sum;
int S,T,dis[N],cur[N],h[N],tot;
queue<int> q;
struct Edge{int v,next,f;}g[N*];
inline int id(int x,int y){return (x-)*m+y;}
inline int min(int x,int y){return x<y?x:y;}
inline void addEdge(int u,int v,int f){
g[++tot].v=v; g[tot].f=f; g[tot].next=h[u]; h[u]=tot;
g[++tot].v=u; g[tot].f=; g[tot].next=h[v]; h[v]=tot;
}
bool bfs(){
while(!q.empty()) q.pop();
q.push(S);
for(int i=;i<=T;i++) dis[i]=-;
dis[S]=;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=h[u],v;i;i=g[i].next)
if(g[i].f&&dis[v=g[i].v]==-){
dis[v]=dis[u]+;
if(v==T) return true;
q.push(v);
}
}
return dis[T]!=-;
}
int dfs(int u,int delta){
if(u==T) return delta;
int ret=,get;
for(int i=cur[u],v;i&δi=g[i].next)
if(g[i].f&&dis[v=g[i].v]==dis[u]+){
get=dfs(v,min(delta,g[i].f));
g[i].f-=get;
g[i^].f+=get;
if(g[i].f) cur[u]=i;
delta-=get;
ret+=get;
}
if(!ret) dis[u]=-;
return ret;
}
int dinic(){
int ret=;
while(bfs()){
for(int i=;i<=T;i++) cur[i]=h[i];
ret+=dfs(S,INF);
}
return ret;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) for(int j=;j<=m;j++) scanf("%d",&a[i][j]),sum+=a[i][j];
for(int i=;i<=n;i++) for(int j=;j<=m;j++) scanf("%d",&b[i][j]),sum+=b[i][j];
for(int i=;i<n;i++) for(int j=;j<=m;j++) scanf("%d",&ax[i][j]),sum+=ax[i][j];
for(int i=;i<n;i++) for(int j=;j<=m;j++) scanf("%d",&bx[i][j]),sum+=bx[i][j];
for(int i=;i<=n;i++) for(int j=;j<m;j++) scanf("%d",&ay[i][j]),sum+=ay[i][j];
for(int i=;i<=n;i++) for(int j=;j<m;j++) scanf("%d",&by[i][j]),sum+=by[i][j];
S=n*m+; T=n*m+; tot=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
int u=id(i,j);
addEdge(S,u,a[i][j]*+ax[i-][j]+ax[i][j]+ay[i][j-]+ay[i][j]);
addEdge(u,T,b[i][j]*+bx[i-][j]+bx[i][j]+by[i][j-]+by[i][j]);
if(i<n){
addEdge(u,id(i+,j),ax[i][j]+bx[i][j]);
addEdge(id(i+,j),u,ax[i][j]+bx[i][j]);
}
if(j<m){
addEdge(u,id(i,j+),ay[i][j]+by[i][j]);
addEdge(id(i,j+),u,ay[i][j]+by[i][j]);
}
}
int get=dinic();
get/=;
printf("%d\n",sum-get);
return ;
}
奇妙代码
【BZOJ2127】happiness的更多相关文章
- 【BZOJ2127】happiness(最小割)
[BZOJ2127]happiness(最小割) 题面 Description 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了, ...
- 【bzoj2127】happiness 最大流
happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 2579 Solved: 1245[Submit][Status][Discuss ...
- 【BZOJ2127】happiness 网络流
题目描述 有\(n\times m\)个人,排成一个\(n\times m\)的矩阵.每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一 ...
- 【BZOJ2127】happiness 最小割
题目大意:有一个$n\times m$的矩阵,矩阵的每个位置上有一个同学,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦 ...
- 【BZOJ2127】happiness(网络流)
点此看题面 大致题意: 每个人只能在文科与理科中选择一种.选择每种科目会带来不同的喜悦值,如果相邻的两位同学选择了同一种科目则会带来额外的喜悦值.求喜悦值总和的最大值. 网络流 这道题做法显然是网络流 ...
- 【bzoj2127】happiness 网络流最小割
题目描述 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文 ...
- 【BZOJ】【2127】happiness
网络流/最小割 Orz Hzwer. 这题他题解说的比较简略……我手画了个图才明白过来…… 嗯对于每个人选文or理的单独收益大家应该很好理解……连S->i 权值为选文的喜悦值,i->T权值 ...
- 【POJ2482】【线段树】Stars in Your Window
Description Fleeting time does not blur my memory of you. Can it really be 4 years since I first saw ...
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
随机推荐
- 《struts2》:指定多个配置文件和默认Action
转载:http://m.blog.csdn.net/article/details?id=51212968
- @interface注解类、 @Target:注解的作用目标 @Retention
public @interface xxx 定义注解 @interface 不是interface,是注解类 是jdk1.5之后加入的,java没有给它新的关键字,所以就用@interface 这么个 ...
- dotween tips
涉及kill及复用的行为比较奇怪. 使用shortcut方式调用dotween时,每次调用都是增加一个新的tweener,如果该tweener控制的属性与上次调用相同时,会出现奇怪的行为,应该是多个t ...
- 反向代理和HTTP重定向
1.什么是正向代理(前向代理)? 在NAT技术(Network Address Translation)出现之前,所有主机无法直接与外网相连,要想上网,需要连接到一台能够访问外网的Web服务器,再通过 ...
- java编码GBK的不可映射字符
编译java文件时,提示编码GBK的不可映射字符. 主要原因:windows 默认编码方式为GBK,用javac编译时,中文按照GBK解析,但是文件内容编码格式不是GBK. 解决:若编译单个文件指定编 ...
- poj2479 最大子段和
题意:给定一个数列.求出数列中不相交的两个子段和,要求和最大 解题思路:对每一个i来说,求出[0-i-1]的最大子段和以及[i-n-1]的最大子段和,再加起来,求出最大的一个.[0-i-1]的最大子段 ...
- Chocolatey 和 Redis windows安装记录
前言 最近研究redis,发现Redis没有官方的windows版本,但MsOpenTech有一直维护对应的Redis版本,其下载地址如下: https://github.com/MSOpenTech ...
- wpf阻止键盘快捷键alt+space,alt+F4
/// <summary> /// 阻止 alt+f4和alt+space 按键 /// </summary> /// <par ...
- Codeforces Round #410 (Div. 2)
Codeforces Round #410 (Div. 2) A B略..A没判本来就是回文WA了一次gg C.Mike and gcd problem 题意:一个序列每次可以把\(a_i, a_{i ...
- Nodejs的运行原理-模块篇
前言 使用Nodejs,就不可避免地引用第三方模块,它们有些是Nodejs自带的(例:http,net...),有些是发布在npm上的(例:mssql,elasticsearch...) 本篇章聚焦3 ...