洛谷:文理分科 传送门

题目描述:

小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想知道,大家应该如何选择,才能使所有人的满意值之和最大。请告诉他这个最大值。

输入输出样例

输入样例:

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 

输出样例:

152

这道题看了很久,在错(D)误(P)的道路上一路狂飙。试了好几种状态,每种状态想了好几种状态转移方程,就是找不到能够证明正确性的解法。厚着脸皮去问大佬,大佬回答:这难道不是傻逼最小割吗?

听了之后我恍然大悟,立马(花了1个小时)找到了正确的模型和正确的建边方式。

把每个人当做一个点那么选文或者选理科就是两个与众不同的集合

首先只考虑前两种情况,即对于每个人只选文科或者选理科的情况。
从源点向每个点连一条边,边权为art,从汇点向每个点连一条边,边权为science。单看这个图直接跑网络流会产生最小割。如果一条边被割断了就表示不选择这个情况。
也就是说:
若源点连出的边被割断了,则表示我不选择文科。同理,若连到汇点的边被割断了就表示不选择理科。

那么前两种情况就处理完了。剩下的就是处理周围4个二货同学的事情了。
对于一个点周围的几个相邻的点的情况,我们新建一个点,将S连向这个点,长度为同时选文可获得的收益,如果该边被割,则说明这些人不同时选文,不能获得同时选文可获得的收益。理科的情况以此类推。
那么怎么保证如果这几个人选相同的科目时能够不割断这个边呢?
从周围这个点向周围的同学连一条INF的边,那么这种情况下都选同一科时,新边肯定不会被割断,就保证了网络流当中的割是使剩下的图满足条件的最小值。
理科的建图就是相反的(从周围的同学连向自己,具体理科建图方式请看代码)。

这个时候网络流中的割就是舍去之后满足条件的需要舍去的值(读着有点拗口)。
根据最大流最小割定理。求出网络流图中的最大流,就是最小割。
那么用总的开心值减去最小割就是最大流了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#define num(i,j) (((i)-1)*m+(j))
using namespace std;
const int maxn=2000010-3;
struct edge
{int v,w,next,fxb;
}e[maxn*10];
int pre[maxn],head[maxn],dis[maxn],num=1,S=1,T;
inline void add_Edge(int u,int v,int w)
{e[num].v=v;e[num].w=w;e[num].next=head[u];e[num].fxb=num+1;head[u]=num;num++;e[num].v=u;e[num].w=0;e[num].next=head[v];e[num].fxb=num-1;head[v]=num;num++;
}
inline bool bfs()
{memset(dis,-1,sizeof(dis));queue<int> q;dis[S]=1;q.push(S);while(!q.empty()){int u=q.front();q.pop();for(register int i=head[u];i;i=e[i].next){int v=e[i].v;if(dis[v]==-1&&e[i].w>0){dis[v]=dis[u]+1;q.push(v);}}}if(dis[T]==-1)return false;elsereturn true;
}
inline int dfs(int x,int f)
{int temp,total=0;if(x==T) return f;for(register int i=pre[x];i;i=e[i].next){int v=e[i].v;if(dis[v]!=dis[x]+1) continue;if(e[i].w<=0)continue;temp=dfs(v,min(f, e[i].w));total+=temp;f-=temp;e[i].w-=temp;e[e[i].fxb].w+=temp;pre[x]=i;if(!f)return total;}return total;
}
#define MAT 510
int c1[4]={0,0,1,-1};
int c2[4]={1,-1,0,0};
int n,m;
inline bool check(int x,int y)
{return x>0&&x<n&&y<m&&y>1;
}
int main()
{int sum=0,newNode,sa,id;scanf("%d%d",&n,&m);S=n*m+1;T=n*m+2,newNode=n*m+2;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){scanf("%d",&sa);id=num(i,j);sum+=sa;add_Edge(S,id,sa);}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){scanf("%d",&sa);id=num(i,j);sum+=sa;add_Edge(id,T,sa);}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){scanf("%d",&sa);id=num(i,j);newNode++;sum+=sa;add_Edge(S,newNode,sa);add_Edge(newNode,id,0x3f3f3f3f);for(int k=0;k<4;k++)if(i+c1[k]>=1&&i+c1[k]<=n&&j+c2[k]>=1&&j+c2[k]<=m)add_Edge(newNode,num(i+c1[k],j+c2[k]),0x3f3f3f3f);}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){scanf("%d",&sa);id=num(i,j);newNode++;sum+=sa;add_Edge(newNode,T,sa);add_Edge(id,newNode,0x3f3f3f3f);for(int k=0;k<4;k++)if( i+c1[k]>=1&&i+c1[k]<=n&&j+c2[k]>=1&&j+c2[k]<=m)add_Edge(num(i+c1[k],j+c2[k]),newNode,0x3f3f3f3f);}int f=0,mincut=0;while(bfs()){memcpy(pre, head, sizeof(head));while(f=dfs(S,0x3f3f3f3f))mincut+=f;}printf("%d\n",sum-mincut);return 0;
}

这个网络流是我直接用的很久之前的板,毕竟很久都没有打过了

LuoguP4313 BZOJ3894 文理分科——最小割相关推荐

  1. bzoj3894 文理分科 最小割

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

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

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

  3. bzoj 3894: 文理分科 最小割

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

  4. BZOJ 3894 Luogu P4313 文理分科 (最小割)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3894 (luogu) https://www.luogu.org/pro ...

  5. BZOJ 3894 文理分科 最小割

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

  6. 【BZOJ3894】文理分科 最小割 (再不刷它就土了,毕竟水题)

    #include <stdio.h> int main() {puts("转载请注明出处[vmurder]谢谢");puts("网址:blog.csdn.ne ...

  7. BZOJ3894 文理分科

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

  8. BZOJ3894: 文理分科

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

  9. BZOJ3894:文理分科

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

最新文章

  1. Mac下 Brew 更新缓慢问题解决(配置清华大学开源软件镜像站)
  2. 零距离感受2015年安全***大赛:静动之美 ***兼备
  3. TCP/IP详解--第四章
  4. 双边滤波算法的原理、流程、实现及效果
  5. 报告软件测试错误的规范
  6. 关注地方门户网站盈利模式
  7. java okhttp https_OkHttp是否支持接受自签名SSL证书?
  8. Openstack介绍
  9. [bash] printf使用范例
  10. 【华为云技术分享】Spark如何与深度学习框架协作,处理非结构化数据
  11. linux 编译环境包,linux上war包编译环境搭建
  12. 【论文复现】Hierarchical Attention Networks for Document Classification
  13. linux服务器运行dyna,dynamips分布式实现详解
  14. c语言dnf脚本源码,dnf纯脚本源码贝贝
  15. 时间片轮转调度算法的模拟时间片轮转调度算法(RR算法)(队尾C++实现)
  16. Spring教程动画文字版2
  17. 简明扼要理解YOLOX
  18. 表的列被set unused的机制
  19. php对接支付宝当面付接口视频教程,支付宝当面付接口demo(面对面扫码支付)
  20. 学生表、班级表、成绩表

热门文章

  1. 天地图实现标注用户当前坐标位置
  2. 谁的用户在世界上是#160;#160;明基决心保时捷设计标准
  3. winform直接控制云台_智云和快手发布重磅功能,手机云台升级,帮8成网民拍大片...
  4. 硬盘无法访问设备硬件出现致命错误,导致请求失败数据找到的法子
  5. 原码/补码的加减运算and溢出判断
  6. 比尔盖茨的风流情史,妻子同意他与前女友同居,婚内出轨损失 80 亿
  7. 什么是大数据?大数据的特点?
  8. 比亚迪元EV汽车拆解报告
  9. openstack-ocata版本nova MQ(rpc)接收端(server)浅析
  10. sinc函数卷积_从采样点到声音:sinc函数和卷积