| Time limit: | 1sec. | Submitted: | 185 |
| Memory limit: | 64M | Accepted: | 109 |
| Xiao Ming is an expert in computer science and technology, so he can get a lot of projects every month. The projects always bring him a lot of money, now he is thinking how to earn money as more as possible. Every month he can get m projects, and each project Ai will bring him Xi yuan. Although Xiao Ming is an expert, he still needs to hire some other guys to help him. Of course, the employees are not as good as Xiao Ming, for they are just good at some single aspect. So, they should work together to finish one project. There is a list shows the salary of m employees, who are labeled from 0 to m-1. Xiao Ming only hires employees, in that list, and he knows who will be needed by each project.If one employee is hired, he can join in several projects.
Input
The first line is an integer c shows the number of cases. For each case, the first line has two numbers m,n(m,n <=100), denoting that there is m projects and n employees on the list.The second line has m integers, which are seperated by a single blank, the ith number Ximeans the project Ai will bring Xiao Ming Xi yuan. Xi is less the 10000. The third line has n integers, which are seperated by a single blank, the ith number Yimeans the employee Bi will cost Xiao Ming Yi yuan. And the next m lines will show which part of the employees will be needed by each project. Line i is a list of the employees, who are needed by project Ai. In each line, first a number Zi shows the number of employees needed by this project. And Zi labels of the emloyees follows, which are still seperated by a sigle blank.
Output
You should output a single integer shows the maximun money Xiao Ming can earn in a single month. The money he can earn is equall to the money he can totally get minus the money he totally cost. You should not leave any extra blanks at the end of each line. Sample Input
1 3 5 30 40 43 55 17 23 22 11 3 0 1 2 3 1 2 3 2 2 1
Sample Output
21
HintIf Xiao Ming can do less project to earn more money, he will certainly do that. |
整个建图过程参考了这个大牛,http://hi.baidu.com/nicyun/blog/item/c02909301cd18a9ca8018e69.html
题目大意:有m个项目要做,有n个工人能做,每个项目要且必须要这些工人中的一个子集来完成,给出每个项目完成后的收益gi和雇佣每个工人的花费ci,以及每个项目必须需要的工人的编号,问能获得的最大收益是多少。
先构图,记起始点为s汇点为t,从s到每个工人wi连一条边容量为ci,从每个项目pi到t连一条边容量为gi,然后若项目pi需要工人wi来完成,则从wi到pi连一条边容量为无穷大。
现在看看此图的最小割有什么含义。(设由最小割划分开与s相连的子图为S,与t相连的子图为T,T中的项目和工人称为被选中的)
1. 若选中的项目pi在T中,因为割中不可能有无限容量的边,则完成此项目所需要的工人也必在T中,这样就保证了割对应的是一个可行的方案。
2. s到每个工人wi的边如果在割中,则此工人是被选中的,如果不在则是未被选中的。
3. 相反,项目pi到t的边如果在割中,则此项目是未被选中的,如果不在则是被选中的。(画个图看看就明白了)
4. 可得出最小割的容量为:被选中的工人花费 + 未被选中的项目收入(1)
又 未被选中的项目收入 = 总的项目收入 - 选中的项目收入(2)
所以可得割的容量为: 总的项目收入 - (被选中的项目收入 - 被选中的工人花费)
可以看出括号中的即为题目要求的ans,设总的项目收入为E,由最小割 == 最大流的定理可得:
ans = E - MaxFlow
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,flow[210][210],dist[210],gap[210];
int find_path(int p, int limit=1<<30-1)
{
if (p == n - 1) return limit;
for (int i = 0; i < n; ++i)
{
if (dist[p] == dist[i] + 1 && flow[p][i] > 0)
{
int t = find_path(i, min(limit, flow[p][i]));
if (t < 0) return t;
if (t > 0)
{
flow[p][i] -= t;
flow[i][p] += t;
return t;
}
}
}
int label = n;
for (int i = 0; i < n; ++i)
if (flow[p][i] > 0) label = min(label, dist[i] + 1);
if (--gap[dist[p]] == 0 || dist[0] >= n) return -1;
++gap[dist[p] = label];
return 0;
}
int iSAP()
{
gap[0] = n;
int maxflow = 0,t = 0;
while ((t = find_path(0)) >= 0) maxflow += t;
return maxflow;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(flow,0,sizeof(flow));
memset(gap,0,sizeof(gap));
memset(dist,0,sizeof(dist));
scanf("%d%d",&n,&m);
int sum=0;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
flow[i+m][n+m+1]=x;
sum+=x;
}
for(int i=1;i<=m;i++)
{
int x;
scanf("%d",&x);
flow[0][i]=x;
}
for(int i=1;i<=n;i++)
{
int t,x;
scanf("%d",&t);
for(int j=1;j<=t;j++)
{
scanf("%d",&x);
x++;
flow[x][i+m]=1<<30-1;
}
}
n=n+m+2;
printf("%d/n",sum-iSAP());
}
return 0;
}
最大收益项目调度
本文介绍了一个计算机科学专家如何通过合理分配项目和员工实现收益最大化的问题。通过构建特定的图模型并利用最小割最大流原理求解,最终实现利益最大化。
776

被折叠的 条评论
为什么被折叠?



