[HOJ2634] How to earn more 最大权闭合子图

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

Hint

If Xiao Ming can do less project to earn more money, he will certainly do that.

题解:

最大权闭合子图水题,每一个工作任务有一条边 容量为输入的利润,每一个员工到汇点有一条边 容量为雇佣费,

每一个工作任务到需要的员工有一条边,容量为INF.

答案就是利润和-最小割

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cstdlib>
 6 using namespace std;
 7 const int N=405,INF=1999999999;
 8 int gi(){
 9     int str=0;char ch=getchar();
10     while(ch>'9'||ch<'0')ch=getchar();
11     while(ch>='0' && ch<='9')str=str*10+ch-'0',ch=getchar();
12     return str;
13 }
14 int n,m,s=0,T,ans=0;
15 int num=1,head[N],q[N],dep[N];
16 struct Lin{
17     int next,to,dis;
18 }a[N*N];
19 void init(int x,int y,int dis){
20     a[++num].next=head[x];
21     a[num].to=y;
22     a[num].dis=dis;
23     head[x]=num;
24     a[++num].next=head[y];
25     a[num].to=x;
26     a[num].dis=0;
27     head[y]=num;
28 } 
29 bool bfs()
30 {
31     memset(dep,0,sizeof(dep));
32     q[1]=s;dep[s]=1;int t=0,sum=1,u,x;
33     while(t!=sum)
34     {
35         x=q[++t];
36         for(int i=head[x];i;i=a[i].next){
37             u=a[i].to;
38             if(dep[u]||a[i].dis<=0)continue;
39             dep[u]=dep[x]+1;q[++sum]=u;
40         }
41     }
42     return dep[T];
43 }
44 int dfs(int x,int flow)
45 {
46     if(x==T || !flow)return flow;
47     int u,tmp,sum=0;
48     for(int i=head[x];i;i=a[i].next){
49         u=a[i].to;
50         if(a[i].dis<=0 || dep[u]!=dep[x]+1)continue;
51         tmp=dfs(u,min(flow,a[i].dis));
52         a[i].dis-=tmp;a[i^1].dis+=tmp;
53         sum+=tmp;flow-=tmp;
54     }
55     return sum;
56 }
57 int maxflow(){
58     int tot=0,tmp;
59     while(bfs()){
60         tmp=dfs(s,INF);
61         while(tmp)tot+=tmp,tmp=dfs(s,INF);
62     }
63     return tot;
64 }
65 void work()
66 {
67     int x,k;
68     m=gi();n=gi();
69     T=n+m+1;
70     for(int i=1;i<=m;i++){
71         x=gi();init(s,i,x);
72         ans+=x;
73     }
74     for(int i=1;i<=n;i++){
75         x=gi();init(i+m,T,x);
76     }
77     for(int i=1;i<=m;i++){
78         k=gi();
79         while(k--){
80             x=gi();init(i,x+m+1,INF);
81         }
82     }
83     printf("%d\n",ans-maxflow());
84 }
85 void Clear(){
86     memset(head,0,sizeof(head));
87     num=1;ans=0;
88 }
89 int main()
90 {
91     int TT=gi();
92     while(TT--){
93         work();
94         Clear();
95     }
96     return 0;
97 }

 

转载于:https://www.cnblogs.com/Yuzao/p/6860840.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值