【题解】 bzoj3894: 文理分科 (网络流/最小割)
Solution:
- 首先这是一个网络流,应该还比较好想,主要就是考虑建图了。
- 我们来分析下题面,因为一个人要么选文科要么选理科,相当于两条流里面割掉一条(怎么想到割我也不知道,颓的题解),那么我们就可以从原点连向每个人,流量为文科愉悦值,然后每个人连向汇点,流量为理科愉悦值。因为要构成最小割,就相当与每条路径一定割一条。
- 然后我们考虑周围人那个情况,拿文科做例子,我们可以从原点连到一个新点,流量为这个额外愉悦值,然后把这个新节点连向这个周围的五个点(或者四/三个点),理科反过来连到汇点即可,至于为什么这样子可以。下面是解释:
我们假设割掉所以与原点(\(1\))与文科特殊情况的新点(\(5\))的那条边(假设为边\(A\),图中标记为\(1\))割掉,如果要不练通,显然所有与汇点相连的边都会要割掉,这时候这条\(A\)边显然可以不割,那么这两条边是不会同时留下的(这其实也是显然) - 然后我们可以求出最小割,每个割表示的是不选哪种情况,那么最小割就是舍弃的愉悦值最小的情况,我们拿所有愉悦值之和减去最小割即可
- 貌似有点点卡常,用当前弧优化可以解决
- 网络流/最小割/费用流的题要多做才会知道建模的套路,不然真的想不到qwq
Code:
//It is coded by ning-mew on 6.28
#include<bits/stdc++.h>
#define FOR for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
using namespace std;
const int maxn=507,INF=1e9+7;
int n,m,S=0,T=maxn*maxn*6-1,ANS=0;
int head[maxn*maxn*6],cnt=-1,last[maxn*maxn*6];
struct Edge{int nxt,to,dis;}edge[maxn*maxn*25];
int art[maxn][maxn],sce[maxn][maxn];
int same_art[maxn][maxn],same_sce[maxn][maxn];
int add_x[5]={0,0,0,1,-1},add_y[5]={0,1,-1,0,0};
int Node(int x,int y,int num){
return n*m*(num-1)+(x-1)*m+y;
}
void add(int from,int to,int dis){
edge[++cnt].nxt=head[from];edge[cnt].to=to;
edge[cnt].dis=dis;head[from]=cnt;
}
void Add(int from,int to,int dis){
//cout<<from<<' '<<to<<' '<<dis<<endl;
add(from,to,dis);add(to,from,0);return;
}
struct Network{
int depth[maxn*maxn*6],mark[maxn*maxn*6];
void clear(){
memset(depth,0,sizeof(depth));
memset(mark,0,sizeof(mark));
}
bool bfs(int x){
queue<int>Q;while(!Q.empty())Q.pop();
Q.push(S);depth[S]=1;mark[S]=x;
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=head[u];i!=-1;i=edge[i].nxt){
int v=edge[i].to;
if(mark[v]!=x&&edge[i].dis>0){
mark[v]=x;depth[v]=depth[u]+1;
Q.push(v);
}
}
}if(mark[T]==x)return true;return false;
}
int dfs(int u,int dist){
if(u==T)return dist;int d=0;
for(int &i=last[u];i!=-1;i=edge[i].nxt){
int v=edge[i].to;
if(mark[v]==mark[u]&&depth[v]==depth[u]+1&&edge[i].dis>0){
d=dfs(v,min(edge[i].dis,dist));
if(d){
edge[i].dis-=d;edge[i^1].dis+=d;
return d;
}
}
}return 0;
}
int Dinic(){ clear();
int ans=0,d=0,x=2;
while(bfs(++x)){
d=dfs(S,INF);
while(d){/*cout<<"Dinic:"<<d<<endl;*/ans+=d;d=dfs(S,INF);}
for(int i=0;i<=m*n*4;i++)last[i]=head[i];last[T]=head[T];
}return ans;
}
}Net;
int main(){
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
FOR scanf("%d",&art[i][j]),ANS+=art[i][j],
Add(S,Node(i,j,1),art[i][j]),Add(Node(i,j,1),Node(i,j,2),INF);
FOR scanf("%d",&sce[i][j]),ANS+=sce[i][j],
Add(Node(i,j,2),T,sce[i][j]);
FOR {
scanf("%d",&same_art[i][j]);ANS+=same_art[i][j];
Add(S,Node(i,j,3),same_art[i][j]);
for(int k=0;k<=4;k++){
int ii=i+add_x[k],jj=j+add_y[k];
if(ii>0&&ii<=n&&jj>0&&jj<=m){
Add(Node(i,j,3),Node(ii,jj,1),INF);
}
}
}
FOR {
scanf("%d",&same_sce[i][j]);ANS+=same_sce[i][j];
Add(Node(i,j,4),T,same_sce[i][j]);
for(int k=0;k<=4;k++){
int ii=i+add_x[k],jj=j+add_y[k];
if(ii>0&&ii<=n&&jj>0&&jj<=m){
Add(Node(ii,jj,2),Node(i,j,4),INF);
}
}
}
printf("%d\n",ANS-Net.Dinic());
return 0;
}
博主蒟蒻,随意转载。但必须附上原文链接:http://www.cnblogs.com/Ning-Mew/,否则你会终生找不到妹子!!!
【题解】 bzoj3894: 文理分科 (网络流/最小割)的更多相关文章
- 【bzoj3894】文理分科 网络流最小割
原文地址:http://www.cnblogs.com/GXZlegend 题目描述 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用 ...
- [Bzoj3894]文理分科(最小割)
Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行描述,每个格子代表一个同学的座位.每位 ...
- D - 文理分科 (网络流->最小割)
题目链接:https://cn.vjudge.net/contest/281959#problem/D 题目大意:中文题目 具体思路:我们需要求出最大的满意值,从另一方面想,我们可以求出总的满意值,然 ...
- 【BZOJ3894】文理分科(最小割)
[BZOJ3894]文理分科(最小割) 题面 BZOJ Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个 ...
- BZOJ_3894_文理分科&&BZOJ_2127_happiness_最小割
BZOJ_3894_文理分科_最小割 Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进 ...
- [BZOJ 3894] 文理分科 【最小割】
题目链接:BZOJ - 3894 题目分析 最小割模型,设定一个点与 S 相连表示选文,与 T 相连表示选理. 那么首先要加上所有可能获得的权值,然后减去最小割,即不能获得的权值. 那么对于每个点,从 ...
- bzoj 3894 文理分科【最小割+dinic】
谁说这道和2127是双倍经验的来着完全不一样啊? 数组开小会TLE!数组开小会TLE!数组开小会TLE! 首先sum统计所有收益 对于当前点\( (i,j) \)考虑,设\( x=(i-1)*m+j ...
- 【bzoj1143】[CTSC2008]祭祀river Floyd+网络流最小割
题目描述 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组成的网络.每条河 ...
- Bzoj3894 文理分科
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 667 Solved: 389 Description 文理分科是一件很纠结的事情!(虽然看到这个题 ...
随机推荐
- CF939D Love Rescue 并查集
传送门 题意:给出两个由小写字母构成的长度相等的字符串$S$与$T$,给出变换$c1\,c2$表示将两个字符串中所有$c1$字符变为$c2$,求将$S$和$T$通过这种变换变为相等字符串的最少变换次数 ...
- Luogu P2048 [NOI2010]超级钢琴
这道题题号很清新啊!第一次开NOI的题,因为最近考到了这道题的升级版. 我们先考虑\(O(n^2)\)大暴力,就是枚举前后端点然后开一个前缀和减一下即可. 然后引入正解,我们设一个三元组\(F(s,l ...
- SequenceFile文件
SequenceFile文件是Hadoop用来存储二进制形式的key-value对而设计的一种平面文件(Flat File).目前,也有不少人在该文件的基础之上提出了一些HDFS中小文件存储的解决方案 ...
- vue-cli 3.0 路由懒加载
当打包构建应用时,Javascript 包会变得非常大,影响页面加载.如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了. 1. 安装 synta ...
- 谈谈ThreadLocal的设计及不足
用Java语言开发的同学对 ThreadLocal 应该都不会陌生,这个类的使用场景很多,特别是在一些框架中经常用到,比如数据库事务操作,还有MVC框架中数据跨层传递.这里我们简要探讨下 Thread ...
- windows 脚本
sudo.vbs http://blog.csdn.net/qidi_huang/article/details/52242053 c:\windows\sudo.vbs 'ShellExecute ...
- Centos下分布式跟踪工具Pinpoint的完整部署记录
一.Pinpoint简单介绍Pinpoint是一款对Java编写的大规模分布式系统的APM工具,有些人也喜欢称呼这类工具为调用链系统.分布式跟踪系统.一般来说,前端向后台发起一个查询请求,后台服务可能 ...
- 《linux内核设计与分析》内核模块编程
内核模块编程 一.准备工作 虚拟机:VMware Workstation 12操作系统:ubuntu当前内核版本:linux-headers-4.4.0-22-generic 二.有关于内核模块的知识 ...
- java-过滤器、拦截器
1.基础知识 1.1面向对象编程(OOP).面向切面编程(AOP) 面向对象编程: 将需求功能划分为不同的.相对独立的和封装良好的类,使他们有属于自己的行为,依靠继承和多态等来定义彼此的关系. 面向切 ...
- 小学生四则运算App实验成果
组名:会飞的小鸟 组员:徐侃 陈志棚 罗伟业 刘芮熔 成员分工: ①刘芮熔:设置安卓包.界面的代码,界面的排序. ②陈志棚:加减乘除的判断异常处理,例如除数不能为零的异常处理等问题. ③徐侃 ...