您的位置:首页 > 其它

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≤ 1000

Solution

一道二元关系的例题。

考虑到是求最大值,那肯定是全部评分和加起来再减去最小割。

至于构图,考虑到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]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: