[2009国家集训队]employ人员雇佣

Time Limit: 20 Sec Memory Limit: 259 MB
Submit: 2240 Solved: 1109
[Submit][Status][Discuss]

Description
作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司。这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j。当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得他的花费,那么作为一个聪明的人,小L当然不会雇佣他。 然而,那些没有被雇佣的人会被竞争对手所雇佣,这个时候那些人会对你雇佣的经理的工作造成影响,使得所赚得的利润减少Ei,j(注意:这里的Ei,j与上面的Ei,j 是同一个)。 作为一个效率优先的人,小L想雇佣一些人使得净利润最大。你可以帮助小L解决这个问题吗?

Input
第一行有一个整数N<=1000表示经理的个数 第二行有N个整数Ai表示雇佣每个经理需要花费的金钱 接下来的N行中一行包含N个数,表示Ei,j,即经理i对经理j的了解程度。(输入满足Ei,j=Ej,i)

Output
第一行包含一个整数,即所求出的最大值。

Sample Input
3

3 5 100

0 6 1

6 0 2

1 2 0

Sample Output
1

【数据规模和约定】

20%的数据中N<=10

50%的数据中N<=100

100%的数据中 N<=1000, Ei,j<=maxlongint, Ai<=maxlongint


一道最小割。

对于两个点的关系,我们可以想到,最小割也就是对这两个点的划分问题求解。

两个点划分不同的集合,求得最大的价值。

不难想到我们总和为E的总和,然后:

  1. 两个点不同集合:花费为 - A - E
  2. 两个点都不选:0
  3. 两个点都选:2E - 2A

然后就可以最小割建图啦。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010,M=3e6+10;
int n,h[N],s,t,x,res;
int head[N],nex[M],to[M],w[M],tot=1;
inline void ade(int a,int b,int c){
	to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;
}
inline void add(int a,int b,int c){
	ade(a,b,c);	ade(b,a,0);
}
inline int bfs(){
	queue<int> q;	q.push(s);	memset(h,0,sizeof h); h[s]=1;
	while(q.size()){
		int u=q.front();	q.pop();
		for(int i=head[u];i;i=nex[i]){
			if(w[i]&&!h[to[i]]){
				h[to[i]]=h[u]+1;	q.push(to[i]);
			}
		}
	}
	return h[t];
}
int dfs(int x,int f){
	if(x==t)	return f;	int fl=0;
	for(int i=head[x];i&&f;i=nex[i]){
		if(h[to[i]]==h[x]+1&&w[i]){
			int mi=dfs(to[i],min(w[i],f));
			w[i]-=mi; w[i^1]+=mi; fl+=mi; f-=mi;
		}
	}
	if(!fl)	h[x]=-1;
	return fl;
}
int dinic(){
	int res=0;
	while(bfs())	res+=dfs(s,inf);
	return res;
}
signed main(){
	cin>>n; t=n+1;
	for(int i=1;i<=n;i++)	cin>>x,add(s,i,x);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%lld",&x);	if(i<=j)	continue; res+=x*2;
			ade(i,j,x*2);	ade(j,i,x*2);	add(i,t,x);	add(j,t,x);
		}
	}
	cout<<res-dinic()<<endl;
	return 0;
}