【JZOJ3990】分配

###Description
【JZOJ3990】分配
###Solution
很明显的二元关系模型。

这里要求最大评分,那么考虑把所有评分加起来,减去最小代价。这里院校相同就会产生代价,那我们把边换一下,源汇交换一下即可。

###Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;++i)
#define fd(i,j,k) for(int i=j;i>=k;--i)
#define rep(i,x) for(int i=ls[x];i;i=nx[i])
using namespace std;
const int N=220,M=42000,_=1000,inf=1e9;
int to[M<<2],nx[M<<2],ls[N<<1],num=1;
int vl[M<<2];
int S,T;
void link(int u,int v,int w){
	to[++num]=v,nx[num]=ls[u],ls[u]=num;
	vl[num]=w;
	to[++num]=u,nx[num]=ls[v],ls[v]=num;
	vl[num]=0;
}
int vis[N<<1];
void dfs(int x){
	vis[x]=1;
	rep(i,x) if(vl[i] && !vis[to[i]]) dfs(to[i]);
}
int dl[N<<1],h[N<<1];
int an[N<<1];
bool bfs(){
	memset(h,0,sizeof(h));
	int l=0,r=1;
	h[dl[1]=S]=1;
	while(l<r){
		int x=dl[++l];
		rep(i,x){
			int v=to[i];
			if(vl[i] && !h[v]) h[v]=h[x]+1,dl[++r]=v;
		}
	}
	return h[T];
}
int flow(int x,int t){
	if(x==T) return t;
	int fl=t;
	rep(i,x){
		int v=to[i];
		if(vl[i] && h[x]+1==h[v]){
			int tmp=flow(to[i],min(t,vl[i]));
			if(tmp){
				vl[i]-=tmp,vl[i^1]+=tmp,t-=tmp;
				if(!t) break;
			}
		}
	}
	if(fl==t) h[x]=-1;
	return fl-t;
}
int main()
{
	int n,m,o;
	scanf("%d %d",&n,&m);
	S=n+m+1,T=S+1;
	int ans=0;
	fo(i,1,n) scanf("%d",&o),ans+=o,link(S,i,o+_);
	fo(i,1,m) scanf("%d",&o),ans+=o,link(i+n,T,o+_);
	fo(i,1,n) scanf("%d",&o),ans+=o,link(i,T,o+_);
	fo(i,1,m) scanf("%d",&o),ans+=o,link(S,i+n,o+_);
	fo(i,1,n)
	fo(j,1,m){
		scanf("%d",&o);
		link(i,j+n,o),link(j+n,i,o);
	}
	int tmp=0;
	while(bfs())
	tmp+=flow(S,inf);
	printf("%d\n",ans+_*(n+m)-tmp);
	dfs(S);
	fo(i,1,n) an[i]=2-vis[i];
	fo(i,n+1,n+m) an[i]=vis[i]+1;
	fo(i,1,n+m) printf("%d ",an[i]);
}

posted @ 2020-12-23 18:38  sadstone  阅读(35)  评论(0编辑  收藏  举报