JZOJ 3990 分配
2018-01-07 11:43
197 查看
分配
Description
今年学院A和学院B分别毕业nA和nB个毕业生,A校的毕业生从1到nA编号,B校的毕业生从nA+1到nA+nB编号。他们每个人都对两个科研院有自己的评分,编号为i的毕业生对研究院X和研究院Y的评分分别为ui和vi。
评分是一个可正可负的整数。
每个毕业生都必须选择两个研究院中的一间进去工作。
如果两个毕业生a和b来自不同的院校,他们进入了相同的研究院,则需要花费Ma,b的磨合成本。
求所有毕业生对自己分配到的院校的评分和,再减去在一起工作的不同院校的磨合成本最大值。
请输出一种可行方案。
Data Constraint
1≤nA,nB≤200,−1000≤ui,vi≤1000,0≤Mi,j≤ 1000Solution
一道二元关系的例题。考虑到是求最大值,那肯定是全部评分和加起来再减去最小割。
至于构图,考虑到A学院的毕业生中不会有边相连,B学院的毕业生中不会有边相连,因此可以巧妙地连边。
对于A学院的一个毕业生i,S表示去X研究院,T表示去Y研究院,S向i连容量为ui的边,同理i向T连一条容量为vi的边。
对于B学院的一个毕业生j,S表示去Y研究院,T表示去X研究院,S向i连容量为vi的边,同理i向T连一条容量为ui的边。
对于任意i∈A,j∈B,i和j之间互连一条容量为Mi,j的边。
跑一边最大流显然就是最小的代价了,进而就能求出答案了。
求最小割的方案的具体方法为从S开始沿着残量网络跑dfs,跑到的点就为S集,剩下的点一定都是T集。
Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define fo(i,j,l) for(int i=j;i<=l;++i) #define fd(i,j,l) for(int i=j;i>=l;--i) using namespace std; typedef long long ll; const ll N=500,zd=1200,maxn=1e7; int f ,c ,bo ; int b ,dq ,h ,vh ,bz ; int na,nb,S,T,n; inline int read() { int o=0,u=1; char ch=' '; for(;(ch<'0'||ch>'9')&&(ch!='-');ch=getchar()); if(ch=='-')u=-1,ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar())o=o*10+ch-48; return o*u; } inline int min(int a,int b) {return a<b?a:b;} void dg(int o) { bz[o]=1; fo(i,1,b[o][0]) if(c[o][b[o][i]]&&!bz[b[o][i]]) dg(b[o][i]); } int flow(int o,int u) { if(o==T)return u; int zx=n+3; fo(j,1,b[o][0]){ dq[o]=dq[o]<b[o][0]?dq[o]+1:1; int i=b[o][dq[o]]; if(c[o][i]){ zx=(zx<h[i]+1)?zx:(h[i]+1); if(h[i]+1==h[o]){ int fff=flow(i,min(u,c[o][i])); if(fff){ c[i][o]+=fff; c[o][i]-=fff; return fff; } if(h[S]>n+2)return 0; } } } if(!(--vh[h[o]]))h[S]=n+3; ++vh[h[o]=zx]; return 0; } int main() { cin>>na>>nb; n=na+nb; S=n+1; T=n+2; ll op=0; fo(i,1,na)c[S][i]=read()+zd,op+=c[S][i]-zd; fo(i,na+1,n)c[i][T]=read()+zd,op+=c[i][T]-zd; fo(i,1,na)c[i][T]=read()+zd,op+=c[i][T]-zd; fo(i,na+1,n)c[S][i]=read()+zd,op+=c[S][i]-zd; b[S][0]=n; fo(i,1,n)b[S][i]=i; fo(i,1,na){ b[i][0]=nb+1; b[i][nb+1]=T; fo(l,1,nb)b[i][l]=na+l; } fo(i,na+1,n){ b[i][0]=na+1; b[i][na+1]=T; fo(l,1,na)b[i][l]=l; } ll ans=-n*zd; fo(i,1,na)fo(l,na+1,n) c[i][l]=c[l][i]=read(); vh[0]=n+2; while(h[S]<=n+2)ans+=flow(S,maxn); ans=op-ans; dg(S); fo(i,1,n)if(bz[i]==0)bz[i]=2; printf("%lld\n",ans); fo(i,1,na)printf("%d ",bz[i]); fo(i,na+1,n)printf("%d ",3-bz[i]); }
相关文章推荐
- 【JZOJ3990】分配
- [JZOJ3990] 分配
- 【时光回溯】【JZOJ3571】【GDKOI2014】内存分配
- Java 内存分配全面浅析
- 数据结构-算法: 分配排序(箱分配排序)
- 探讨C++ 变量生命周期、栈分配方式、类内存布局、Debug和Release程序的区别(二)
- 【JZOJ5434】【NOIP2017提高A组集训10.30】Matrix
- JZOJ 4888 【NOIP2016提高A组集训第14场11.12】最近公共祖先
- 明晰C++内存分配的五种方法的区别
- [转]jBPM4.4之(Task)任务分配
- JZOJ 5425 数论
- 动态内存分配如何工作?
- 动态内存分配(转抄)
- 深入Java核心 Java内存分配原理精讲
- JZOJ5439. 【NOIP2017提高A组集训10.31】Calculate 乱搞
- 为什么Java程序占用的内存比实际分配给它的要多
- java中内存分配
- ROS(mikrotik)用PCQ实现线路带宽的平均分配
- 今天遇到一个关于对象和对象方法内存分配的有趣的问题
- Android 优化二 Java内存分配机制及内存泄漏