BZOJ_2039_[2009国家集训队]employ人员雇佣_ 最小割

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



转化为损失最少的最小割模型。

建立$S$,$T$分别表示选或不选,便于用$S$,$T$割集表示方案。

然后设两个经理$i$和$j$,连这样几条边$S->i(x1),S->j(x2),i->j(x3),i->T(x4),j->T(x5)$,括号内代表容量,$x$为设的未知数。

假设$i$和$j$都选,那么要割掉到$T$的两条边$x4+x5$。假设都不选,则需要割掉$S$连出的两条边$x1+x2$。

$i$选$j$不选,则需要割掉$x2+x3+x4$三条边。

然后分别和真正的收益对应一下,可以得到$x1=\sum\limits_{k=1}^{n}e[i][k]$ $x3=2*e[i][j]$ $x4=a[i]$。

于是建图跑最小割即可。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
inline char nc() {
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd() {
    register int x=0;
    register char s=nc();
    while(s<‘0‘||s>‘9‘) s=nc();
    while(s>=‘0‘&&s<=‘9‘) x=(x<<3)+(x<<1)+s-‘0‘,s=nc();
    return x;
}
#define N 1050
#define M 3000050
#define S (n+1)
#define T (n+2)
#define inf (1ll<<60)
int n,a[N],e[N][N];
struct Dinic {
    int head[N],to[M],nxt[M],cnt;
    int dep[N],Q[N],l,r;
    ll flow[M],sum;
    inline void add(int u,int v,ll f) {
        to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f;
        to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0;
    }
    bool bfs() {
        memset(dep,0,sizeof(dep));
        l=r=0; Q[r++]=S; dep[S]=1;
        while(l<r) {
            int x=Q[l++],i;
            for(i=head[x];i;i=nxt[i]) {
                if(!dep[to[i]]&&flow[i]) {
                    dep[to[i]]=dep[x]+1;
                    if(to[i]==T) return 1;
                    Q[r++]=to[i];
                }
            }
        }
        return 0;
    }
    ll dfs(int x,ll mf) {
        if(x==T) return mf;
        ll nf=0;
        int i;
        for(i=head[x];i;i=nxt[i]) {
            if(dep[to[i]]==dep[x]+1&&flow[i]) {
                ll tmp=dfs(to[i],min(mf-nf,flow[i]));
                if(!tmp) dep[to[i]]=0;
                nf+=tmp;
                flow[i]-=tmp;
                flow[i^1]+=tmp;
                if(nf==mf) break;
            }
        }
        return nf;
    }
    void dinic() {
        ll f;
        while(bfs()) while((f=dfs(S,inf))!=0) sum-=f;
        printf("%lld\n",sum);
    }
}G;
int main() {
    G.cnt=1;
    n=rd();
    int i,j;
    for(i=1;i<=n;i++) a[i]=rd();
    for(i=1;i<=n;i++) {
        ll now=0;
        for(j=1;j<=n;j++) {
            e[i][j]=rd();
            G.sum+=e[i][j];
            now+=e[i][j];
            G.add(i,j,2*e[i][j]);
        }
        G.add(S,i,now);
        G.add(i,T,a[i]);
    }
    G.dinic();
}

原文地址:https://www.cnblogs.com/suika/p/9032522.html

时间: 2024-08-27 08:42:59

BZOJ_2039_[2009国家集训队]employ人员雇佣_ 最小割的相关文章

【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.当然,雇佣每一个经理都需要花费一定

[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做出贡献,使得所赚得的利

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 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

2009国家集训队 employ人员雇佣

Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j.当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得他的花费,那么作为一个聪明的人,小L当然不会雇佣他. 然而,那些没有被雇佣的人会被竞争对手所雇佣,这个时候那些人会对你雇佣的经理的工作造成影响

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

任意门 Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j.当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得他的花费,那么作为一个聪明的人,小L当然不会雇佣他. 然而,那些没有被雇佣的人会被竞争对手所雇佣,这个时候那些人会对你雇佣的经理的工作

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 [2009国家集训队]employ人员雇佣 网络流

链接 BZOJ 2039 题解 这题建图好神,自己瞎搞了半天,最后不得不求教了企鹅学长的博客,,,,发现建图太神了!! s向每个人连sum(e[i][x]) 的边,每个人向T连a[i]的边.两两人之间连2 * e[i][j]的边即可. 最后总的e – maxflow即为答案. 为什么我就没想到"源点向每个人连sum(e[i][x]) 的边"-- 犯的错误: 为了方便,对于双向边,用ADD(u, v, w), ADD(v, u, w)代替了ADD(u, v, w), ADD(v, u,

【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,对于一些经理可能他做出的贡献不值得