zoukankan      html  css  js  c++  java
  • 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

    第一行包含一个整数,即所求出的最大值。

    看起来好像是网络流???

    辣就想想吧……

    代价就是每个点连到汇点就可以了,可是收益???

    如果用同样的方法处理收益,那么意义是两个人都选就获得E,选一个无影响,都不选失去E。

    然而真实情况是选一个失去E,都不选无影响。

    那么考虑平衡选一个和不选的情况,观察+尝试发现,只要在点i和点j之间连一条2*E的边就可以惹。

    #include<cstdio>
    #include<algorithm>
    #define MN 40001
    #define int long long
    using namespace std;
    
    int read_p,read_ca,read_f;
    inline int read(){
        read_p=0;read_ca=getchar();read_f=1;
        while(read_ca<'0'||read_ca>'9') read_f=read_ca=='-'?-1:read_f,read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p*read_f;
    }
    const int INF=1e18;
    struct na{int y,z,ne;}b[MN*100];
    int n,m,a[1001],num=1,no=0,S,T,mmh=0,g[MN],c[MN],d[MN],l[MN];
    inline void in(int x,int y,int z){b[++num].y=y;b[num].z=z;b[num].ne=l[x];l[x]=num;}
    inline void add(int x,int y,int z,int Z=0){in(x,y,z);in(y,x,Z);}
    inline int min(int a,int b){return a<b?a:b;}
    int sap(int x,int f){
        if (x==T) return f;
        int h=0,q;
        for (int i=d[x];i;i=b[i].ne)
        if (b[i].z&&g[b[i].y]+1==g[x]){
            q=sap(b[i].y,min(b[i].z,f-h));
            h+=q;b[i].z-=q;b[i^1].z+=q;
            if (h==f||g[S]==no) return h;
        }
        if (!(--c[g[x]])) g[S]=no;d[x]=l[x];c[++g[x]]++;
        return h;
    }
    signed main(){
        register int i,j;
        n=read();S=n+1;T=no=n+2;
        for (i=1;i<=n;i++) add(i,T,read());
        for (i=1;i<=n;i++)
        for (j=1;j<=n;j++) m=read(),mmh+=m,a[j]+=m,add(i,j,m,m);
        for (i=1;i<=n;i++) add(S,i,a[i]);
        for (;g[S]<no;mmh-=sap(i,INF));
        printf("%lld
    ",mmh);
    }
    View Code
  • 相关阅读:
    c++ 网络编程(四) LINUX/windows下 socket 基于I/O复用的服务器端代码 解决多进程服务端创建进程资源浪费问题
    c++ 网络编程(三) LINUX/windows 进程间的通信原理与实现代码 基于多进程的服务端实现
    c++ 网络编程(二) linux 下多进程socket通信 多个客户端与单个服务端交互代码实现回声服务器
    c++ 网络编程(一)TCP/UDP windows/linux 下入门级socket通信 客户端与服务端交互代码
    c++ MFC图像处理CImage类常用操作代码
    vue 模板语法
    占位1
    MongoDB
    Node.js fs-文件系统
    nodeJs 常用模块(一)
  • 原文地址:https://www.cnblogs.com/Enceladus/p/6935062.html
Copyright © 2011-2022 走看看