BZOJ 3894 网络流最小割 解题报告
来源:互联网 发布:数据一致性数据治理 编辑:程序博客网 时间:2024/06/05 20:40
Description
文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过)
小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想知道,大家应该如何选择,才能使所有人的满意值之和最大。请告诉他这个最大值。
Input
第一行为两个正整数:n,m
接下来n术m个整数,表示art[i][j];
接下来n术m个整数.表示science[i][j];
接下来n术m个整数,表示same_art[i][j];
Output
输出为一个整数,表示最大的满意值之和
Sample Input
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
Sample Output
152
【解题报告】
(原谅我没有买权限号,我也不知道我能不能A。。。)
令S集为学文,T集为学理。
每个人学文或者学理的满意度很好连边。
如果某个集合内的人都学理会获得一个满意度,那么就新加一个点,将集合内的所有人向这个点连流量为正无穷的边,再从这个点向T连一条流量为满意度的边,表示集合内任意一个人学文都要把这个点与T的边割掉。
都学文同理。
建完图之后跑最小割即可。
自己画了个图,应该会更形象些。
大神题解http://blog.csdn.net/PoPoQQQ/article/details/43968017
代码如下:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=3e4+10;const int M=1e6+5;const int inf=1e8;const int dx[5]={0,1,-1,0,0};const int dy[5]={0,0,0,1,-1};struct edge { int next,to,f; edge(){} edge(int _n,int _t,int _f):next(_n),to(_t),f(_f){}}e[M];int n,m,S,T,ans;int w[105][105],cnt_p;int first[N],tot=1;int q[N],d[N];inline void Add_Edges(int x,int y,int f) { e[++tot]=edge(first[x],y,f),first[x]=tot; e[++tot]=edge(first[y],x,0),first[y]=tot;}bool bfs() { int l,r,x; memset(d,-1,sizeof(d)); d[q[1]=S]=1; for(l=r=1;l!=r+1;++l) for(x=first[q[l]];x;x=e[x].next) if(!~d[e[x].to]&&e[x].f) { d[q[++r] = e[x].to] = d[q[l]] + 1; if(e[x].to == T) return 1; } return 0;}int dfs(int p,int lim) { if (p==T||!lim) return lim; int x,tmp,rest=lim; for(x=first[p];x&&rest;x=e[x].next) if(d[e[x].to]==d[p]+1&&((tmp=min(e[x].f,rest))>0)) { rest-=(tmp=dfs(e[x].to,tmp)); e[x].f-=tmp,e[x^1].f+=tmp; if(!rest) return lim; } if(rest) d[p]=-1; return lim-rest;}inline int Dinic() { int res=0; while(bfs()) res+=dfs(S, inf); return res;}inline bool in(int x, int y) { return x&&y&&x<=n&&y<=m;}#define X i+dx[k]#define Y j+dy[k]#define p1(i,j) w[i][j]*3#define p2(i,j) w[i][j]*3+1#define p3(i,j) w[i][j]*3+2int main() { int i,j,k,x; scanf("%d%d",&n,&m); for (i=1;i<=n;++i) for (j=1;j<=m;++j) w[i][j]=++cnt_p; S =n*m*3+3,T=S+1; for(i=1;i<=n;++i) for(j=1;j<=m;++j) { scanf("%d",&x); Add_Edges(S,p1(i,j),x),ans+=x; } for(i=1;i<=n;++i) for(j=1;j<=m;++j) { scanf("%d",&x); Add_Edges(p1(i,j),T,x),ans+=x; } for(i=1;i<=n;++i) for(j=1;j<=m;++j) { scanf("%d",&x); Add_Edges(S,p2(i,j),x), ans+=x; for(k=0;k<=4;++k) if(in(X,Y)) Add_Edges(p2(i,j),p1(X,Y),inf); } for(i=1;i<=n;++i) for(j=1;j<=m;++j) { scanf("%d",&x); Add_Edges(p3(i,j),T,x),ans+=x; for(k=0;k<=4;++k) if(in(X,Y)) Add_Edges(p1(X,Y),p3(i,j),inf); } printf("%d\n",ans-Dinic()); return 0;}
- BZOJ 3894 网络流最小割 解题报告
- BZOJ 3144 网络流最小割 解题报告
- BZOJ 1001 网络流最小割 解题报告
- BZOJ 3894 文理分科 解题报告 最小割 网络流 DINIC
- bzoj 3144 切糕 最小割 解题报告
- BZOJ 1475 最小割 解题报告
- CodeVS 1907 网络流最小割 解题报告
- HOJ 2634 网络流最小割 解题报告
- URAL 1277 网络流最小割 解题报告
- SPOJ 1693 网络流最小割 解题报告
- BZOJ 2400(网络流最小割)
- bzoj 3894(最小割)
- BZOJ 2561 最小生成树 网络流 最小割
- Codeforces 808F 网络流最小割(二分图最大点权独立集) 解题报告
- BZOJ-3894 文理分科 网络流建图 最小割 Dinic
- Bzoj:1324:Exca王者之剑:网络流,最小割
- bzoj 2229: [Zjoi2011]最小割 分治&网络流
- [BZOJ]1797: [Ahoi2009]Mincut 最小割 网络流+强连通
- View绘制
- TCP为什么需要三次握手,又为什么需要4次挥手?
- HDFS的API调用,创建Maven工程,创建一个非Maven工程,HDFS客户端操作数据代码示例,文件方式操作和流式操作
- A+B Problem (64bit Integer + EOF)
- opencv3_java 添加mask掩码 AddMask
- BZOJ 3894 网络流最小割 解题报告
- windows平台上php程序处理高并发的解决方法
- 十分钟搞定pandas
- 数据库连接池
- 砝码称重
- caffe——常用层及其参数
- OpenGL蓝宝书源码学习(九)第五章——纹理基础篇
- 使用ajax验证用户名是否重复
- LeetCode-49:Group Anagrams