2039: [2009国家集训队]employ人员雇佣
Time Limit: 20 Sec Memory Limit: 259 MB
Submit: 1988 Solved: 951
[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
分析:
最小割。
s连i 权值为ai
i连t 权值为∑e[i][j]
i连j 权值为2 * e[i][j]
想了半天,我还是滚回去好好啃啃各种论文把。。
AC代码:
# include <iostream> # include <cstdio> # include <queue> # include <cstring> using namespace std; typedef long long LL; const LL inf = 1e16; const int N = 2e3 + 12; int head[N],dt,s,t,cur[N],dep[N],n;LL bac; struct Edge{ int to,nex;LL res; }edge[N * N]; void AddEdge(int u,int v,LL w) { edge[dt] = (Edge){v,head[u],w}; head[u] = dt++; edge[dt] = (Edge){u,head[v],0}; head[v] = dt++; } queue<int> Q; bool Bfs() { for(int i = s;i <= t;i++)dep[i] = -1; dep[s] = 1;Q.push(s);int u; while(!Q.empty()) { u = Q.front();Q.pop(); for(int i = head[u];~i;i = edge[i].nex)if(dep[edge[i].to] == -1 && edge[i].res) { dep[edge[i].to] = dep[u] + 1; Q.push(edge[i].to); } } return dep[t] != -1; } LL dfs(int u,LL f) { if(u == t || !f)return f; LL flow = 0,D; for(int &i = cur[u];~i;i = edge[i].nex)if(dep[edge[i].to] == dep[u] + 1 && (D = dfs(edge[i].to,min(f,edge[i].res)))) { edge[i].res -= D;edge[i ^ 1].res += D; f -= D;flow += D; if(!f)break; } return flow; } LL Dinic() { LL flow = 0; while(Bfs()) { for(int i = s;i <= t;i++)cur[i] = head[i]; flow += dfs(s,inf); } return flow; } int main() { memset(head,-1,sizeof head); scanf("%d",&n);s = 0;t = n + 1; LL x,ret; for(int i = 1;i <= n;i++)scanf("%lld",&x),AddEdge(s,i,x); for(int i = 1;i <= n;i++) { ret = 0; for(int j = 1;j <= n;j++) { scanf("%lld",&x); AddEdge(i,j,x << 1LL);bac += x; ret += x; } AddEdge(i,t,ret); } printf("%lld\n",bac - Dinic()); }
原文地址:https://www.cnblogs.com/lzdhydzzh/p/8782587.html
时间: 2024-10-12 18:53:55