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

来源:互联网 发布:制作宝宝照片的软件 编辑:程序博客网 时间:2024/05/21 12:08

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

题目传送门

woc我竟然一A了这道题(虽然有点慢),但是一A啊,心里美滋滋~~
看着看着这道题,越想越像一道题我做过的,欸,这好像是最大全闭合子图啊
淦,看着离机房关闭时间还有半个小时,码!

不对,这不是最大权闭合子图,它不是个二分图啊!
那怎么做??最小割吗??
是啊,这不是最小割模型吗??

由st向每个经理连流量为总赚钱的边
由每个经理向ed连流量为雇佣费用的边
最后两两经理之间连流量为2*关系值的边,因为他们相互影响
淦!

代码如下:

#include<cmath>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;const ll INF=1e17;struct node{    int x,y,next,other;    ll c;}a[2100000];int len,last[2100000];void ins(int x,int y,ll c){    int k1,k2;    k1=++len;    a[len].x=x;a[len].y=y;a[len].c=c;    a[len].next=last[x];last[x]=len;    k2=++len;    a[len].x=y;a[len].y=x;a[len].c=0;    a[len].next=last[y];last[y]=len;    a[k1].other=k2;    a[k2].other=k1;}int head,tail,h[3100000];int st,ed,list[2100000];bool bt_h(){    memset(h,0,sizeof(h));h[st]=1;    list[1]=st;head=1;tail=2;    while(head<tail)    {        int x=list[head];        for(int k=last[x];k;k=a[k].next)        {            int y=a[k].y;            if(h[y]==0&&a[k].c>0)            {                h[y]=h[x]+1;                list[tail++]=y;            }        }        head++;    }    if(h[ed]>0)return true;    return false;}int findflow(int x,ll f){    if(x==ed)return f;    ll s=0,t;    for(int k=last[x];k;k=a[k].next)    {        int y=a[k].y;        if(h[y]==h[x]+1&&a[k].c>0&&s<f)        {            s+=(t=findflow(y,min(a[k].c,f-s)));            a[k].c-=t;a[a[k].other].c+=t;        }    }    if(s==0)h[x]=0;    return s;}ll c[1100];int main(){    int n;int sum=0;    scanf("%d",&n);st=0,ed=n+1;    len=0;memset(last,0,sizeof(last));    for(int i=1;i<=n;i++){ll x;scanf("%lld",&x);ins(i,ed,x);}    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)        {            ll x;            scanf("%lld",&x);            if(i==j)continue;            sum+=x;c[i]+=x;            ins(i,j,2*x);        }    for(int i=1;i<=n;i++)ins(0,i,c[i]);    ll ans=0;    while(bt_h()==true)ans+=findflow(st,INF);    printf("%lld\n",sum-ans);    return 0;}

by_lmy

阅读全文
1 0