【BZOJ2127】happiness 网络流
题目描述
有\(n\times m\)个人,排成一个\(n\times m\)的矩阵。每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。问全班喜悦值的和最大是多少。
\(n,m\leq 100\)
题解
先把问题简化,考虑只有两个人,甲选文科的喜悦值为\(a\),甲选理科的喜悦值为\(b\),乙选文科的喜悦值为\(c\),乙选理科的喜悦值为\(d\),两人同时选文科的喜悦值为\(e\),两人同时选理科的喜悦值为\(f\)。
两个人同时选文或同时选理会有额外喜悦值,这并不太好处理。考虑转化一下。先把两人选文的喜悦值\(a,c\)加上两人同时选文科的喜悦值的一半\(\frac{e}{2}\)。如果只有一人选(即两人选的不同),那么就要减掉\(\frac{e}{2}\)。理科同理。
这样就是一个网络流的标准模型了。
最后拿\(a+b+c+d+e+f\)减掉最小割就是答案。
\(e,f\)有可能是奇数,可以把所有边的容量\(\times 2\),最后再除回来。
可以得到以下的网络:
多个人的情况和两个人的情况类似,合在一起处理即可。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
if(a>b)
swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
int rd()
{
int s=0,c;
while((c=getchar())<'0'||c>'9');
do
{
s=s*10+c-'0';
}
while((c=getchar())>='0'&&c<='9');
return s;
}
int upmin(int &a,int b)
{
if(b<a)
{
a=b;
return 1;
}
return 0;
}
int upmax(int &a,int b)
{
if(b>a)
{
a=b;
return 1;
}
return 0;
}
int v[1000010];
int w[1000010];
int t[1000010];
int h[10010];
int cnt=0;
void add(int x,int y,int z)
{
cnt++;
v[cnt]=y;
w[cnt]=z;
t[cnt]=h[x];
h[x]=cnt;
}
int S,T;
int d[10010];
int e[10010];
int cur[10010];
int num;
int op(int x)
{
return ((x-1)^1)+1;
}
queue<int> q;
void bfs()
{
memset(d,-1,sizeof d);
memcpy(cur,h,sizeof h);
q.push(T);
d[T]=0;
int i,x;
while(!q.empty())
{
x=q.front();
q.pop();
e[d[x]]++;
for(i=h[x];i;i=t[i])
if(w[op(i)]&&d[v[i]]==-1)
{
d[v[i]]=d[x]+1;
q.push(v[i]);
}
}
}
int dfs(int x,int flow)
{
if(x==T)
return flow;
int s=0,c;
int &i=cur[x];
for(;i;i=t[i])
if(d[v[i]]==d[x]-1&&w[i])
{
c=dfs(v[i],min(flow,w[i]));
s+=c;
flow-=c;
w[i]-=c;
w[op(i)]+=c;
if(!flow)
return s;
}
e[d[x]]--;
if(!e[d[x]])
d[S]=num;
e[++d[x]]++;
cur[x]=h[x];
return s;
}
int maxflow()
{
bfs();
int ans=0;
while(d[S]<=num-1)
ans+=dfs(S,0x7fffffff);
return ans;
}
int m1[110][110];
int m2[110][110];
int m3[110][110];
int m4[110][110];
int m5[110][110];
int m6[110][110];
int n,m;
int id(int x,int y)
{
return (x-1)*m+y;
}
int a1[110][110];
int a2[110][110];
int a3[110][110];
int a4[110][110];
int main()
{
open("bzoj2127");
scanf("%d%d",&n,&m);
int i,j;
int sum=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&m1[i][j]);
sum+=2*m1[i][j];
a1[i][j]+=2*m1[i][j];
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&m2[i][j]);
sum+=2*m2[i][j];
a2[i][j]+=2*m2[i][j];
}
for(i=1;i<n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&m3[i][j]);
sum+=2*m3[i][j];
a1[i][j]+=m3[i][j];
a1[i+1][j]+=m3[i][j];
a3[i][j]+=m3[i][j];
}
for(i=1;i<n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&m4[i][j]);
sum+=2*m4[i][j];
a2[i][j]+=m4[i][j];
a2[i+1][j]+=m4[i][j];
a3[i][j]+=m4[i][j];
}
for(i=1;i<=n;i++)
for(j=1;j<m;j++)
{
scanf("%d",&m5[i][j]);
sum+=2*m5[i][j];
a1[i][j]+=m5[i][j];
a1[i][j+1]+=m5[i][j];
a4[i][j]+=m5[i][j];
}
for(i=1;i<=n;i++)
for(j=1;j<m;j++)
{
scanf("%d",&m6[i][j]);
sum+=2*m6[i][j];
a2[i][j]+=m6[i][j];
a2[i][j+1]+=m6[i][j];
a4[i][j]+=m6[i][j];
}
num=n*m+2;
S=n*m+1;
T=n*m+2;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
add(S,id(i,j),a1[i][j]);
add(id(i,j),S,0);
add(id(i,j),T,a2[i][j]);
add(T,id(i,j),0);
}
for(i=1;i<n;i++)
for(j=1;j<=m;j++)
{
add(id(i,j),id(i+1,j),a3[i][j]);
add(id(i+1,j),id(i,j),a3[i][j]);
}
for(i=1;i<=n;i++)
for(j=1;j<m;j++)
{
add(id(i,j),id(i,j+1),a4[i][j]);
add(id(i,j+1),id(i,j),a4[i][j]);
}
int ans=maxflow();
ans=sum-ans;
ans>>=1;
printf("%d\n",ans);
return 0;
}
【BZOJ2127】happiness 网络流的更多相关文章
- 【bzoj2127】happiness 网络流最小割
题目描述 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文 ...
- bzoj2127: happiness(双倍经验最小割)
2127: happiness 题目:传送门 题解: 双倍经验美滋滋~ 请看蒟蒻以前写的渣题解...bzoj3894 表示做完自己就最小割了... 代码(直接改的...菜啊): #include< ...
- bzoj2127: happiness
Description 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友 ...
- [bzoj2127]happiness——最小割
这个题太恶心了...并不想继续做了... 本代码在bzoj上TLE! 大致说一下思路: 建立ST,首先由S连边(S,u,a)a代表学文的分数,连向T(u,T,b)b表示学理的分数,这样构造出了两个人独 ...
- BZOJ 2127 happiness ——网络流
[题目分析] 基本上是第一次真正的使用最小割的模型. 同时加上一个数然后最后再减去是处理负数的一种方法. 设立出来最小割的模型然后解方程是一件很重要的事情,建议取一个相对来说比较简单的值带入求解. 这 ...
- 【BZOJ2127】happiness(网络流)
点此看题面 大致题意: 每个人只能在文科与理科中选择一种.选择每种科目会带来不同的喜悦值,如果相邻的两位同学选择了同一种科目则会带来额外的喜悦值.求喜悦值总和的最大值. 网络流 这道题做法显然是网络流 ...
- 【BZOJ2127】happiness(最小割)
[BZOJ2127]happiness(最小割) 题面 Description 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了, ...
- 文理分科 BZOJ3894 & happiness BZOJ2127
分析: 最小割(一开始我没看出来...后来经过提点,大致理解...),不选则割的思想. 我们先这样考虑,将和选理相关的和S相连,与选文相关的和T相连,如果没有第二问,那么建图就是简单的S连cnt,cn ...
- 【bzoj2127】happiness 最大流
happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 2579 Solved: 1245[Submit][Status][Discuss ...
随机推荐
- Python_装饰器进阶_32
#带参数的装饰器 #500个函数 import time FLAGE = True def timmer_out(flag): def timmer(func): def inner(*args,** ...
- H5 69-清除浮动方式四
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- H5 55-行高
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Wannafly挑战赛28
总结- A-开始觉得是找规律,最开始模拟当时我觉得如果L达到1e9的范围的话,岂不是要加1e9次,模拟也就没有认真写,现在想来,后面由于加的不再是1,而是我前面的值,这样相当了一个斐波那契的类型,而斐 ...
- java中流的简单小结
1.分类 按字节流分: InputStream(输出流) OutputStream(输入流) 按字符流分: Reader Writer 提示:输入.输出是站在程序的角度而言,所有输入流是“读 ...
- jmeter高并发设计方案(转)
高并发设计方案二(秒杀架构) 优化方向: (1)将请求尽量拦截在系统上游(不要让锁冲突落到数据库上去).传统秒杀系统之所以挂,请求都压倒了后端数据层,数据读写锁冲突严重,并发高响应慢,几乎所有请求都超 ...
- vue传参
<template> <ul> <li v-for="item in list" :key="item.id"> <b ...
- 微信小程序错误码参考大全
开发过程中,会遇到很多微信返回的状态码,鬼知道代表什么意思,现在好了,整理总结了一份状态码,方便大家. 转载:http://www.yiyongtong.com/archives/view-1856- ...
- PhpStorm本地断点调试
一.断点调试php环境搭建 1.检测本地php环境是否安装了Xdebug 在本地输出phpinfo():搜索Xdebug;如下图 如果没有安装,安装操作Xdebug如下: 将phpinfo();的信 ...
- Python:matplotlib绘制线条图
线型图是学习matplotlib绘图的最基础案例.我们来看看具体过程: 下面我们将两条曲线绘制到一个图形里: 可以看到这种方式下,两个线条共用一个坐标轴,并且自动区分颜色. plot方法的核心是 ...