【BZOJ2039】【2009国家集训队】employ人员雇佣 最小割

转载请注明出处:http://blog.csdn.net/vmurder/article/details/42651751

其实我就是觉得原创的访问量比未授权盗版多有点不爽233。。。

最小割心得:

首先需要一定的功底来发现这道题是最小割,并且投入思考。

然后想怎么建图:

最小割都是先算上所有收益,然后再通过网络图进行割边减去部分权值。

收益有时候可能带上负值。

然后我们需要思考什么能带来权值,什么会有权值冲突。

而最小割图一般都是拆成S集和T集考虑,即取与不取,某人/点选A或者选B等等,

这样就会带来冲突,也就是需要割的边。

然后我们需要把所有权值的得与失列出来,针对性建图,然后check几种情况:

比如两个人都在S集、都在T集,甲S乙T,甲T乙S等等,我们看这样会割掉哪些边,失去哪些权值。

如果发现建错了,也可以有针对性地进行修改。

就说这么多吧。

下面说这道题的建图:

点:每个人一个点,额外设源汇点。

边:

源向人连这个人能造成的全部收益(当作雇佣所有人,然后此人造成的收益)

人与人之间连两人熟悉度*2,呃,题意问题。

人向汇连雇佣需要花的钱。

分析一下

一个人雇与不雇造成的收益/损失,

两个人都雇、都不雇、雇一个造成的损失,

就很容易明白这个建图了。

代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1005
#define M 2001000
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3fLL
using namespace std;
struct KSD
{
	int v,next;
	long long len;
}e[M];
int head[N],cnt;
inline void add(int u,int v,long long len)
{
	e[++cnt].v=v;
	e[cnt].len=len;
	e[cnt].next=head[u];
	head[u]=cnt;
}
int s,t,d[N];
queue<int>q;
bool bfs()
{
	memset(d,0,sizeof(d));
	while(!q.empty())q.pop();
	int i,u,v;
	q.push(s),d[s]=1;
	while(!q.empty())
	{
		u=q.front(),q.pop();
		for(i=head[u];i;i=e[i].next)
		{
			if(!d[v=e[i].v]&&e[i].len)
			{
				d[v]=d[u]+1;
				if(v==t)return 1;
				q.push(v);
			}
		}
	}
	return 0;
}
long long dinic(int x,long long flow)
{
	if(x==t)return flow;
	long long remain=flow,k;
	int i,v;
	for(i=head[x];i&&remain;i=e[i].next)
	{
		if(d[v=e[i].v]==d[x]+1&&e[i].len)
		{
			k=dinic(v,min(remain,e[i].len));
			if(!k)d[v]=0;
			e[i].len-=k,e[i^1].len+=k;
			remain-=k;
		}
	}
	return flow-remain;
}
int n;
long long cost[N],map[N][N],sum[N];
long long res,maxflow;
void build()
{
	int i,j,k;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%lld",&cost[i]);
	for(i=1;i<=n;i++)for(j=1;j<=n;j++)scanf("%lld",&map[i][j]),sum[i]+=map[i][j];
		cnt=1,s=n+1,t=n+2;
	for(i=1;i<=n;i++)add(s,i,sum[i]),add(i,s,0),res+=sum[i];
	for(i=1;i<=n;i++)add(i,t,cost[i]),add(t,i,0);
	for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)add(i,j,2*map[i][j]),add(j,i,2*map[i][j]);
}
int main()
{
//	freopen("test.in","r",stdin);
	build();
	while(bfs())maxflow+=dinic(s,inf);
	printf("%d\n",res-maxflow);
	return 0;
}
时间: 2024-10-13 15:37:04

【BZOJ2039】【2009国家集训队】employ人员雇佣 最小割的相关文章

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

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

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

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

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人员雇佣_ 最小割

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

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当然不会雇佣他. 然而,那些没有被雇佣的人会被竞争对手所雇佣,这个时候那些人会对你雇佣的经理的工作

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,