[题解]bzoj2039(2009国家集训队)employ人员雇佣
来源:互联网 发布:深圳返享网络 编辑:程序博客网 时间:2024/05/19 13:30
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
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
【数据规模和约定】
20%的数据中N<=10
50%的数据中N<=100
100%的数据中 N<=1000, Ei,j<=maxlongint, Ai<=maxlongint
Solution
网络流最小割。构图首先按照惯例,S向每个人连这个人所能造成的所有的价值(雇佣所有人的情况),每个人向T连雇佣他的花费。关键问题是如何处理经理相互影响的状况。当两个经理一个选一个不选的时候,我们不仅要割掉一个经理的价值和另一个经理的雇佣费用,还需要承受两个经理之间的影响后果。相当于我们不但不能获得E[i,j]的收益,还要倒扣E[i,j]的收益,相当于割掉一条边权为2*E[i,j]的边。所以我们这么构图:
然后跑一边最大流,用所有人都雇佣的最大收益减去最大流就得到答案。
代码:
#include<cstdio>#include<algorithm>#include<cstring>#include<climits>using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f;} typedef long long LL;const int maxn=1010;struct edge{ int to,next,same; LL size;}e[maxn*maxn*3];const LL oo=LONG_LONG_MAX;int E[maxn][maxn],n,a[maxn],num=0,head[maxn];int que[maxn],dep[maxn],cur[maxn];LL sum[maxn],ans=0; void adde(int u,int v,LL w){ e[++num].to=v;e[num].size=w; e[num].next=head[u]; head[u]=num;}void add(int u,int v,LL w){ adde(u,v,w);e[num].same=num+1; adde(v,u,0);e[num].same=num-1;}bool bfs(){ memset(que,0,sizeof que); memset(dep,0,sizeof dep); int qhead=0,tail=1; que[1]=0;dep[0]=1; while(qhead<tail){ int now=que[++qhead]; for(int i=head[now];i;i=e[i].next){ if(!dep[e[i].to]&&e[i].size){ que[++tail]=e[i].to; dep[e[i].to]=dep[now]+1; if(e[i].to==n+1)return true; } } } return false;}LL dfs(int x,LL flow){ if(x==n+1||(!flow))return flow; LL temp; for(int &i=cur[x];i;i=e[i].next){ if(dep[e[i].to]==dep[x]+1&&(temp=dfs(e[i].to,min(flow,e[i].size)))){ e[i].size-=temp; e[e[i].same].size+=temp; return temp; } } return 0;}void Dinic(){ while(bfs()){ int flow; memcpy(cur,head,sizeof head); while((flow=dfs(0,oo))){ ans-=flow; } }} int main(){ n=read(); for(int i=1;i<=n;i++){ a[i]=read(); add(i,n+1,a[i]); } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ E[i][j]=read(); if(i!=j)add(i,j,E[i][j]<<1); sum[i]+=E[i][j]; } } for(int i=1;i<=n;i++){ add(0,i,sum[i]); ans+=sum[i]; } Dinic(); printf("%lld\n",ans); return 0;}
0 0
- [题解]bzoj2039(2009国家集训队)employ人员雇佣
- bzoj2039: [2009国家集训队]employ人员雇佣
- bzoj2039 [2009国家集训队]employ人员雇佣
- BZOJ2039: [2009国家集训队]employ人员雇佣
- BZOJ2039: [2009国家集训队]employ人员雇佣
- 【BZOJ2039】【2009国家集训队】employ人员雇佣 最小割
- 【bzoj2039】[2009国家集训队]employ人员雇佣 最小割
- 【BZOJ2039】[2009国家集训队]employ人员雇佣【最小割】
- [BZOJ2039][2009国家集训队]employ人员雇佣(最小割)
- 2039: [2009国家集训队]employ人员雇佣
- BZOJ2039 employ人员雇佣
- BZOJ 2039 2009国家集训队 employ人员雇佣 最小割
- BZOJ 2039: [2009国家集训队]employ人员雇佣
- BZOJ 2039: [2009国家集训队]employ人员雇佣 最小割 二元组建图模型
- [bzoj2039][网络流-最小割]employ人员雇佣
- bzoj2039 人员雇佣 最小割
- BZOJ2039 人员雇佣-最小割
- 国家集训队1999-2009论文集
- 多线程4-线程状态与常用方法
- hdu 5919 Sequence II(主席树)
- [华为OJ--C++]087-在字符串中找出连续最长的数字串
- I/O复用:pselect
- 单链表功能大全
- [题解]bzoj2039(2009国家集训队)employ人员雇佣
- Codeforces Round #398 (Div. 2) A Snacktower
- jstee--基础用法
- MATLAB实现最大类间方差算法
- Java的native关键字
- Jedis的使用
- linkedlist
- Python学习--21 电子邮件
- linux bash脚本监控启动停止weblogic服务