分配
Description
今年学院
A
和学院
他们每个人都对两个科研院有自己的评分,编号为
i
的毕业生对研究院
评分是一个可正可负的整数。
每个毕业生都必须选择两个研究院中的一间进去工作。
如果两个毕业生
a
和
求所有毕业生对自己分配到的院校的评分和,再减去在一起工作的不同院校的磨合成本最大值。
请输出一种可行方案。
Data Constraint
1
≤
Solution
一道二元关系的例题。
考虑到是求最大值,那肯定是全部评分和加起来再减去最小割。
至于构图,考虑到
A
学院的毕业生中不会有边相连,
对于
A
学院的一个毕业生
对于
B
学院的一个毕业生
对于任意 i∈A , j∈B ,i和j之间互连一条容量为 Mi,j 的边。
跑一边最大流显然就是最小的代价了,进而就能求出答案了。
求最小割的方案的具体方法为从
S
开始沿着残量网络跑
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[N][N],c[N][N],bo[N];
int b[N][N],dq[N],h[N],vh[N],bz[N];
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]);
}