码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-04-10 21:54:15      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:problems   一个   limit   bfs   time   最大值   竞争   while   影响   

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


 

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

HINT


 

 

Source


 

版权所有者: 林衍凯

 

 

分析:


最小割。
s连i 权值为ai

i连t 权值为∑e[i][j]

i连j  权值为2 * e[i][j]
想了半天,我还是滚回去好好啃啃各种论文把。。

AC代码:


 

# include <iostream>
# include <cstdio>
# include <queue>
# include <cstring>
using namespace std;
typedef long long LL;
const LL inf = 1e16;
const int N = 2e3 + 12;
int head[N],dt,s,t,cur[N],dep[N],n;LL bac;
struct Edge{
    int to,nex;LL res;
}edge[N * N];
void AddEdge(int u,int v,LL w)
{
    edge[dt] = (Edge){v,head[u],w};
    head[u] = dt++;
    edge[dt] = (Edge){u,head[v],0};
    head[v] = dt++;
}
queue<int> Q;
bool Bfs()
{
    for(int i = s;i <= t;i++)dep[i] = -1;
    dep[s] = 1;Q.push(s);int u;
    while(!Q.empty())
    {
     u = Q.front();Q.pop();
     for(int i = head[u];~i;i = edge[i].nex)if(dep[edge[i].to] == -1 && edge[i].res)
     {
        dep[edge[i].to] = dep[u] + 1;
        Q.push(edge[i].to);
     }
    }
    return dep[t] != -1;
}
LL dfs(int u,LL f)
{
    if(u == t || !f)return f;
    LL flow = 0,D;
    for(int &i = cur[u];~i;i = edge[i].nex)if(dep[edge[i].to] == dep[u] + 1 && (D = dfs(edge[i].to,min(f,edge[i].res))))
    {
        edge[i].res -= D;edge[i ^ 1].res += D;
        f -= D;flow += D;
        if(!f)break;
    }
    return flow;
}
LL Dinic()
{
    LL flow = 0;
    while(Bfs())
    {
        for(int i = s;i <= t;i++)cur[i] = head[i];
        flow += dfs(s,inf);
    }
    return flow;
}
int main()
{
  memset(head,-1,sizeof head);
  scanf("%d",&n);s = 0;t = n + 1;
  LL x,ret;
  for(int i = 1;i <= n;i++)scanf("%lld",&x),AddEdge(s,i,x);
  for(int i = 1;i <= n;i++)
  {
   ret = 0;
   for(int j = 1;j <= n;j++)
   {
       scanf("%lld",&x);
       AddEdge(i,j,x << 1LL);bac += x;
       ret += x;
   }
   AddEdge(i,t,ret);
  }
  printf("%lld\n",bac - Dinic());
}

 

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

标签:problems   一个   limit   bfs   time   最大值   竞争   while   影响   

原文地址:https://www.cnblogs.com/lzdhydzzh/p/8782587.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!