【BZOJ2039】【2009国家集训队】人员雇佣 [最小割]

人员雇佣

Time Limit: 20 Sec  Memory Limit: 259 MB
[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

HINT

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

Main idea

  给定若干关系,选择一个人需要固定的费用,对于i,j,选择了其中一个则损失E[i][j],两个都选了则获得2*E[i][j],问能获得的最大价值。

Source

  显然就是一个最小割的模型,我们直接套用论文里面的模型即可。

  针对于这道题,我们对于代价建图,用Ans=总和-最小代价即可。

  对于第i个点,如果选了,会损失a[i],连边(S,i,a[i]):表示选了它之后的代价;如果不选,会损失ΣE[i][j],所以连边(i,T,ΣE[i][j]),表示不选的损失。

  然后对于一对点i,j,连边(i,j,2*E[i][j]),表示如果不选i,选了j的话,本来i中选j的利益得不到,又要损失j对i的影响为E[i][j],一共损失了2*E[i][j]。

  然后求一下最小割即可。

Code

  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cmath>
  8 #include<map>
  9 using namespace std;
 10
 11 typedef long long s64;
 12 const int ONE=5000005;
 13 const s64 INF=21474836400000;
 14
 15 int n,x;
 16 s64 res;
 17 int tou,wei,S,T;
 18 int Dep[ONE],q[1000001],E[ONE];
 19 int next[ONE],first[ONE],go[ONE],tot;
 20 s64 w[ONE];
 21 s64 Ans;
 22
 23 int get()
 24 {
 25         int res=1,Q=1;char c;
 26         while( (c=getchar())<48 || c>57 )
 27         if(c==‘-‘)Q=-1;
 28         res=c-48;
 29         while( (c=getchar())>=48 && c<=57 )
 30         res=res*10+c-48;
 31         return res*Q;
 32 }
 33
 34 int Add(int u,int v,s64 z)
 35 {
 36         next[++tot]=first[u];   first[u]=tot;   go[tot]=v;  w[tot]=z;
 37         next[++tot]=first[v];   first[v]=tot;   go[tot]=u;  w[tot]=0;
 38 }
 39
 40 int Bfs()
 41 {
 42         memset(Dep,0,sizeof(Dep));
 43         tou=0;  wei=1;
 44         q[1]=S; Dep[S]=1;
 45         for(int i=S;i<=T;i++) E[i]=first[i];
 46         while(tou<wei)
 47         {
 48             int u=q[++tou];
 49             for(int e=first[u];e;e=next[e])
 50             {
 51                 int v=go[e];
 52                 if(Dep[v] || !w[e]) continue;
 53                 Dep[v]=Dep[u]+1;
 54                 q[++wei]=v;
 55             }
 56         }
 57         return (Dep[T]>0);
 58 }
 59
 60 s64 Dfs(int u,s64 Limit)
 61 {
 62         if(u==T || !Limit) return Limit;
 63         s64 from=0,f;
 64         for(int &e=E[u];e;e=next[e])
 65         {
 66             int v=go[e];
 67             if(Dep[v]!=Dep[u]+1 || !w[e]) continue;
 68             f=Dfs(v,min(Limit,w[e]));
 69             w[e]-=f;
 70             w[((e-1)^1)+1]+=f;
 71             Limit-=f;
 72             from+=f;
 73             if(!Limit) break;
 74         }
 75         return from;
 76 }
 77
 78 int main()
 79 {
 80         n=get();
 81         S=0;    T=n+1;
 82         for(int i=1;i<=n;i++)
 83         {
 84             x=get();
 85             Add(S,i,x);
 86         }
 87
 88         for(int i=1;i<=n;i++)
 89         {
 90             res=0;
 91             for(int j=1;j<=n;j++)
 92             {
 93                 x=get();
 94                 res+=x; Ans+=x;
 95                 Add(i,j,2*x);
 96             }
 97             Add(i,T,res);
 98         }
 99
100         while(Bfs()) Ans-=Dfs(S,INF);
101
102         printf("%lld",Ans);
103
104 }

时间: 2024-10-01 03:13:51

【BZOJ2039】【2009国家集训队】人员雇佣 [最小割]的相关文章

P1791 [国家集训队]人员雇佣

P1791 [国家集训队]人员雇佣 首先假设所有工作人员都是己方的,现在收益是$\sum_{i!=j}2E[i][j]$,然后现在可以选一些人,炒掉其他的 对编号为$i$的人来说,选择不炒他会获得$-A[i]$的收益,所以每个点向T连一条边,权值为$A[i]$ 然后,对每个点对$(i,j) (i<j)$,从S向i,j都连一条权值为E[i][j]的边,ij互相连权值为2E[i][j]的边 那么这样为啥是对的呢 如果两个都选,只需要总体割掉$A(i)(i\rightarrow T),A(j)(j\r

[Bzoj2039][2009国家集训队]employ人员雇佣(最小割)

2039: [2009国家集训队]employ人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1988  Solved: 951[Submit][Status][Discuss] Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利

【BZOJ2039】【2009国家集训队】employ人员雇佣 最小割

转载请注明出处:http://blog.csdn.net/vmurder/article/details/42651751 其实我就是觉得原创的访问量比未授权盗版多有点不爽233... 最小割心得: 首先需要一定的功底来发现这道题是最小割,并且投入思考. 然后想怎么建图: 最小割都是先算上所有收益,然后再通过网络图进行割边减去部分权值. 收益有时候可能带上负值. 然后我们需要思考什么能带来权值,什么会有权值冲突. 而最小割图一般都是拆成S集和T集考虑,即取与不取,某人/点选A或者选B等等, 这样

BZOJ 2039 2009国家集训队 employ人员雇佣 最小割

题目大意:给定n个人,每个人有一个佣金,i和j如果同时被雇佣会产生2*E(i,j)的效益,i和j如果一个被雇佣一个不被雇佣会产生E(i,j)的亏损,求最大收益 首先对于每一个cost[i],从点i出发向汇点连一条流量为cost[i]的边 对于每一对点(i,j),建图如下: 从S向点i和点j各连一条流量为E(i,j)的边 i和j之间连一条流量为2*E(i,j)的双向边 这样可以保证每种割法对应一种雇佣方案 用矩阵上数字的总和减掉最小割即是答案 边集会很大,因此合并后再加即可 #include <c

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

一开始就知道是最小割模型,然后开始乱搞建图,发现自己想错了... Orz PoPoQQQ,还给蒟蒻提供了很多帮助! 1 /************************************************************** 2 Problem: 2039 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:5984 ms 7 Memory:64264 kb 8 *************************

BZOJ 2039 人员雇佣(最小割)

最小割的建图模式一般是,先算出总收益,然后再通过网络模型进行割边减去部分权值. 然后我们需要思考什么才能带来收益,什么才能有权值冲突. s连向选的点,t连向不选的点,那么收益的减少量应该就是将s集和t集分开的割边集. 下面说这道题的建图: 点: 每个人一个点,额外设源汇点. 边: 源向人连这个人能造成的全部收益(当作雇佣所有人,然后此人造成的收益) 人与人之间连两人熟悉度*2,呃,题意问题. 人向汇连雇佣需要花的钱. # include <cstdio> # include <cstri

【BZOJ 2039】 2039: [2009国家集训队]employ人员雇佣 (最小割)

2039: [2009国家集训队]employ人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1511  Solved: 728 Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j.当然,雇佣每一个经理都需要花费一定

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

2039: [2009国家集训队]employ人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1369  Solved: 667[Submit][Status][Discuss] Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利

【BZOJ 2038】 [2009国家集训队]小Z的袜子(hose)

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MB Submit: 2839  Solved: 1269 [Submit][Status] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命-- 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完