文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠
结过)
小P所在的班级要进行文理分科。他的班级可以用一个n*m的矩阵进行
描述,每个格子代表一个同学的座位。每位同学必须从文科和理科中选择
一科。同学们在选择科目的时候会获得一个满意值。满意值按如下的方式
得到:
.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如
果选择理科,将得到science[i][j]的满意值。
.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻当且
仅当它们拥有一条相同的边)的同学全部选择了文科,则他会更开
心,所以会增加same_art[i][j]的满意值。
.如果第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 Sample Output

题意:给定一个N*M的矩阵,每个格子的人可以学文或者学理,学文和学理各有一个满意度,如果以某人为中心的十字内所有人都学文或者学理都会得到一个额外满意度,求最大满意度之和。

思路:BZOJ上面有很多此类题型,用网络里解决的方案大概有两种。

解法1:直接建图求最大流,源点S为学理,汇点T为学文。然后对于学理的“组合”,加一个点W:由源点S加边指向W,容量为组合的收益;W加边指向组合的成员,容量为inf。  同样的,对于学文的“组合”,加一个点E:由E加边指向汇点T,容量为组合的收益;组合的成员加边指向E,容量为inf。 然后求出最小割。

有:ans=sum-maxflow  

解法2:先假设全部学理科,再把边权做差(学理-学文的净收益),再求最大闭合权子图:原点与代价点连接,收益点与汇点连接; 收益和-最大流=最大净收益。 那么现在的基本代价或者收益是ai-bi,。然后破坏集合的代价是c1i,得到集合的收益是c2i。 差不多就酱紫。具体的请去看popoqqq的题解。

体会:解法2更有道理一些,但是解法1更通用,无论“有格外收益的组合”长什么样子,都可以轻松加边,然后求最大流。

解法1的代码:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=;
const int inf=;
int N,M,S,T,ans,maxflow;
int Laxt[maxn],To[maxn],Next[maxn],cap[maxn],cnt=;
int vd[maxn],dis[maxn];
int xx[]={,,,,-};
int yy[]={,,-,,};
void add(int u,int v,int c)
{
Next[++cnt]=Laxt[u];
Laxt[u]=cnt;
To[cnt]=v;
cap[cnt]=c;
}
int id(int u,int v){
return (u-)*M+v;
}
int sap(int u,int flow)
{
if(flow==||u==T) return flow;
int tmp,delta=;
for(int i=Laxt[u];i;i=Next[i]){
if(dis[u]==dis[To[i]]+&&cap[i]>){
tmp=sap(To[i],min(cap[i],flow-delta));
delta+=tmp;
cap[i]-=tmp;
cap[i^]+=tmp;
if(delta==flow||dis[S]>T+) return delta;
}
}
vd[dis[u]]--;
if(vd[dis[u]]==) dis[S]=T+;
vd[++dis[u]]++;
return delta;
}
int main()
{
int i,j,k,x; scanf("%d%d",&N,&M);
S=; T=*N*M+;
for(i=;i<=N;i++)
for(j=;j<=M;j++){
scanf("%d",&x); ans+=x;
add(S,id(i,j),x); add(id(i,j),S,);
}
for(i=;i<=N;i++)
for(j=;j<=M;j++){
scanf("%d",&x); ans+=x;
add(id(i,j),T,x); add(T,id(i,j),);
}
for(i=;i<=N;i++)
for(j=;j<=M;j++){
scanf("%d",&x); ans+=x;
add(S,N*M+id(i,j),x); add(N*M+id(i,j),S,);
for(k=;k<=;k++){
int x=i+xx[k],y=j+yy[k];
if(x>=&&x<=N&&y>=&&y<=M){
add(N*M+id(i,j),id(x,y),inf); add(id(x,y),N*M+id(i,j),);
}
}
}
for(i=;i<=N;i++)
for(j=;j<=M;j++){
scanf("%d",&x); ans+=x;
add(*N*M+id(i,j),T,x); add(T,*N*M+id(i,j),);
for(k=;k<=;k++){
int x=i+xx[k],y=j+yy[k];
if(x>=&&x<=N&&y>=&&y<=M){
add(id(x,y),*N*M+id(i,j),inf); add(*N*M+id(i,j),id(x,y),);
}
}
}
while(dis[S]<=T) maxflow+=sap(S,inf);
printf("%d\n",ans-maxflow);
return ;
}

BZOJ3894:文理分科(最大流)(同BZoj3438)的更多相关文章

  1. 【bzoj3894】文理分科 网路流

    [bzoj3894]文理分科 2015年3月25日3,4002 Description  文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过)  小P所在的班级要进行文理分科.他的班 ...

  2. [bzoj3894]文理分科_网络流_最小割

    文理分科 bzoj-3894 题目大意:题目链接. 注释:略. 想法: 这种题也是一种套路. 我们新建一个点表示收益点. 然后把所有的收益都加一起,求最小割表示代价即可. Code: #include ...

  3. Bzoj3894 文理分科

    Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 667  Solved: 389 Description  文理分科是一件很纠结的事情!(虽然看到这个题 ...

  4. BZOJ3894文理分科——最小割

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

  5. [Bzoj3894]文理分科(最小割)

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

  6. bzoj3894: 文理分科(还是那道最小割)

    3894: 文理分科 题目:传送门 感谢波老师没有来D飞我,让我做出了这题... 题解: 这题其实和我做的上一题(bzoj2132)很像,所以就不写题意了. 依然是那最小割... 这题给出了四个利益矩 ...

  7. 【题解】 bzoj3894: 文理分科 (网络流/最小割)

    bzoj3894,懒得复制题面,戳我戳我 Solution: 首先这是一个网络流,应该还比较好想,主要就是考虑建图了. 我们来分析下题面,因为一个人要么选文科要么选理科,相当于两条流里面割掉一条(怎么 ...

  8. [BZOJ3894]文理分科(最小割)

    (1) 对每个位置建一个点F1,S向这个点连art[i][j]的边,这个点向T连science[i][j]的边. (2) 对每个位置再建一个点F2,S向这个点连same_art[i][j]的边,这个点 ...

  9. 【BZOJ3894】文理分科(最小割)

    [BZOJ3894]文理分科(最小割) 题面 BZOJ Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个 ...

随机推荐

  1. ubuntu16.04 python3.5 opencv的安装与卸载(转载)

    转载https://blog.csdn.net/qq_37541097/article/details/79045595 Ubuntu16.04 自带python2.7和python3.5两个版本,默 ...

  2. Thinkphp5 模块的自动生成

    首先到根目录下的build.php文件中去 是这样子滴: 然后去public目录中的index.php中去添加代码 这样子: 然后运行项目 就搞定了. 是不是美滋滋! 在public 下index.p ...

  3. mac 中终端查看ip 采用 ifconfig

  4. JDBC 插入大批量数据

    时不时会有大量数据的插入操作,方式有多种,效率不同: 1. statement 2. prepareStatement 3. statement/prepareStatement + batch 4. ...

  5. 讲一下numpy的矩阵特征值分解与奇异值分解

    1.特征值分解 主要还是调包: from numpy.linalg import eig 特征值分解:  A = P*B*PT  当然也可以写成 A = QT*B*Q  其中B为对角元为A的特征值的对 ...

  6. wireshark抓取mysql数据包

    最近在学习搭建数据库服务,因为跟产品相关所以需要从流量中拿到mysql的数据包.然后就想着在本机搭建mysql数据库,然后连接,用wireshark抓就行了. MySQL搭建用的是XAMPP,想说XA ...

  7. HDU 5694 分治+规律

    http://acm.hdu.edu.cn/showproblem.php?pid=5694 此题一开始我也找到了规律,也知道是分治可是,,,想的太复杂了没写开, 我一直想的通过L,R两个参数分治,可 ...

  8. centos7 rabbitmq 安装

    http://www.rabbitmq.com/install-rpm.html Overview rabbitmq-server is included in Fedora. However, th ...

  9. Repeat a string repeat a string

    重要的事情说3遍! 重复一个指定的字符串 num次,如果num是一个负数则返回一个空字符串. 这是一些对你有帮助的资源: Global String Object 这道题的思路就是按照题目要求一步一步 ...

  10. Accesshelper.cs

    using System; using System.Data; using System.Data.OleDb; using System.Collections; using System.IO; ...