zoukankan      html  css  js  c++  java
  • 【BZOJ 2039】 2039: [2009国家集训队]employ人员雇佣 (最小割)

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

    Time Limit: 20 Sec  Memory Limit: 259 MB
    Submit: 1511  Solved: 728

    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集表示雇佣,T集表示不雇佣。每个经理拆成x,y两点。s向所有x点连,流量为雇佣费用。对于每个Ei,j,i,j经理连一条流量为2*Ei,j的无向边,同时i和j都向t连流量为Ei,j的边,最小割为所有Ei,j*2减最大流。由于边数大,需要合并一下边。

      【啊一开始构错图了,好桑心。。。。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 #define Maxn 1100
      9 #define INF 0xfffffff
     10 
     11 int mymin(int x,int y) {return x<y?x:y;}
     12 
     13 int a[Maxn],w[Maxn][Maxn];
     14 
     15 struct node
     16 {
     17     int x,y,f,next,o;
     18 }t[Maxn*Maxn*10];
     19 int len,first[Maxn];
     20 
     21 void ins(int x,int y,int f)
     22 {
     23     t[++len].x=x;t[len].y=y;t[len].f=f;
     24     t[len].next=first[x];first[x]=len;t[len].o=len+1;
     25     t[++len].x=y;t[len].y=x;t[len].f=0;
     26     t[len].next=first[y];first[y]=len;t[len].o=len-1;
     27 }
     28 
     29 int st,ed;
     30 int dis[Maxn];
     31 queue<int > q;
     32 bool bfs()
     33 {
     34     for(int i=1;i<=ed;i++) dis[i]=-1;
     35     while(!q.empty()) q.pop();
     36     dis[st]=0;q.push(st);
     37     while(!q.empty())
     38     {
     39         int x=q.front();
     40         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     41         {
     42             int y=t[i].y;
     43             if(dis[y]==-1)
     44             {
     45                 dis[y]=dis[x]+1;
     46                 q.push(y);
     47             }
     48         }
     49         q.pop();
     50     }
     51     if(dis[ed]==-1) return 0;
     52     return 1;
     53 }
     54 
     55 int ffind(int x,int flow)
     56 {
     57     if(x==ed) return flow;
     58     int now=0;
     59     for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     60     {
     61         int y=t[i].y;
     62         if(dis[y]==dis[x]+1)
     63         {
     64             int a=ffind(y,mymin(flow-now,t[i].f));
     65             t[i].f-=a;
     66             t[t[i].o].f+=a;
     67             now+=a;
     68         }
     69         if(now==flow) break;
     70     }
     71     if(now==0) dis[x]=-1;
     72     return now;
     73 }
     74 
     75 void output()
     76 {
     77     for(int i=1;i<=len;i+=2)
     78     {
     79         printf("%d -> %d %d
    ",t[i].x,t[i].y,t[i].f);
     80     }printf("
    ");
     81 }
     82 
     83 int ans;
     84 void max_flow()
     85 {
     86     while(bfs())
     87     {
     88         ans-=ffind(st,INF);
     89     // output();
     90     // while(1);
     91     }
     92 }
     93 
     94 int s[Maxn];
     95 
     96 int main()
     97 {
     98     int n;
     99     scanf("%d",&n);
    100     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    101     ans=0;
    102     for(int i=1;i<=n;i++)
    103     {
    104         s[i]=0;
    105         for(int j=1;j<=n;j++)
    106         {
    107             scanf("%d",&w[i][j]);
    108             s[i]+=w[i][j];
    109             ans+=w[i][j];
    110         }
    111     }
    112      
    113     len=0;
    114     memset(first,0,sizeof(first));
    115     st=n+1;ed=st+1;
    116     for(int i=1;i<=n;i++) ins(st,i,a[i]);
    117     for(int i=1;i<=n;i++)
    118      for(int j=i+1;j<=n;j++) {ins(i,j,2*w[i][j]);ins(j,i,2*w[i][j]);}
    119     for(int i=1;i<=n;i++) ins(i,ed,s[i]);
    120     // output();
    121     max_flow();
    122     printf("%d
    ",ans);
    123     return 0;
    124 }
    View Code

    2017-03-28 20:58:42

  • 相关阅读:
    汉语编程
    第一次作业
    个人总结
    psp表格
    第三次个人作业——用例图设计
    第二次结对作业
    第一次结对作业
    第二次个人编程作业
    第一次编程作业
    第一次博客作业
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6636832.html
Copyright © 2011-2022 走看看