zoukankan      html  css  js  c++  java
  • BZOJ 2039: [2009国家集训队]employ人员雇佣

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

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

    [Submit][Status][Discuss]

    建图求最小割:

    假设一开始获得了所有的Wij,ans = ΣWij。

    加入使用一个经理,产生代价是Costi,从源点向该点连Costi的边。

    两个经理之间互相影响,如果在两人之间断开,及选取两人中的一个,那么将失去一开始得到的Wij,并且还会损失Wij的竞争代价,所以连边2*Wij。

    我们也可以直接选择放弃一个经理,失去所有其本算在答案中的贡献,即ΣWij,其中j=1..n。

    最终ans - 最小割就是答案。

      1 #include <cstdio>
      2 #include <cstring>
      3 
      4 const int siz = 4000010;
      5 const int inf = 1000000007;
      6 
      7 int n;
      8 
      9 int tot;
     10 int s, t;
     11 int hd[siz];
     12 int to[siz];
     13 int fl[siz];
     14 int nt[siz];
     15 
     16 inline void add(int u, int v, int f)
     17 {
     18 //    printf("add %d %d %d
    ", u, v, f);
     19     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; hd[u] = tot++;
     20     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; hd[v] = tot++;
     21 }
     22 
     23 int dep[siz];
     24 
     25 inline bool bfs(void)
     26 {
     27     static int que[siz];
     28     static int head, tail;
     29     
     30     memset(dep, 0, sizeof(dep));
     31     dep[que[head = 0] = s] = tail = 1;
     32     
     33     while (head != tail)
     34     {
     35         int u = que[head++], v;
     36         for (int i = hd[u]; ~i; i = nt[i])
     37             if (fl[i] && !dep[v = to[i]])
     38                 dep[que[tail++] = v] = dep[u] + 1;
     39     }
     40     
     41     return dep[t];
     42 }
     43 
     44 int cur[siz];
     45 
     46 inline int min(int a, int b)
     47 {
     48     return a < b ? a : b;
     49 }
     50 
     51 int dfs(int u, int f)
     52 {
     53     if (u == t || !f)
     54         return f;
     55     
     56     int used = 0, flow, v;
     57     
     58     for (int i = hd[u]; ~i; i = nt[i])
     59         if (fl[i] && dep[v = to[i]] == dep[u] + 1)
     60         {
     61             flow = dfs(v, min(f - used, fl[i]));
     62             used += flow;
     63             fl[i] -= flow;
     64             fl[i ^ 1] += flow; 
     65             if (used == f)
     66                 return f;
     67             if (fl[i])
     68                 cur[u] = i;
     69         }
     70         
     71     if (!used)
     72         dep[u] = 0;
     73     
     74     return used;
     75 }
     76 
     77 inline int maxFlow(void)
     78 {
     79     int maxFlow = 0, newFlow;
     80     
     81     while (bfs())
     82     {
     83         for (int i = s; i <= t; ++i)
     84             cur[i] = hd[i];
     85             
     86         while (newFlow = dfs(s, inf))
     87             maxFlow += newFlow;
     88     }
     89             
     90     return maxFlow;
     91 }
     92 
     93 int ans;
     94 int sum;
     95 
     96 signed main(void)
     97 {
     98     scanf("%d", &n);
     99     
    100     s = 0, t = n + 1;
    101     
    102     memset(hd, -1, sizeof(hd));
    103     
    104     for (int i = 1, x; i <= n; ++i)
    105         scanf("%d", &x), add(s, i, x);
    106         
    107     for (int i = 1; i <= n; ++i)
    108     {
    109         sum = 0;
    110         
    111         for (int j = 1; j <= n; ++j)
    112         {
    113             int x; scanf("%d", &x);
    114             ans += x;
    115             sum += x;
    116             if (i != j)
    117                 add(i, j, x << 1);
    118         }
    119         
    120         add(i, t, sum);
    121     }
    122         
    123     printf("%d
    ", ans - maxFlow());
    124 }

    @Author: YouSiki

  • 相关阅读:
    linux mint使用起來比較穩定
    ubntu下的记录软件brasero ,mint内置
    [Enterprise Library]Data (二)DataCollection
    jquery 获取标签名
    谁会做logo呢
    供用淘宝卖家常用的称谓:各位亲,跨年,诸事顺利~
    rails缓存 学习
    test
    jquery 复习基础知识
    开机改用nginx启动,停止apache2的开机启动
  • 原文地址:https://www.cnblogs.com/yousiki/p/6249508.html
Copyright © 2011-2022 走看看