[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 }

 

posted @ 2017-05-16 13:08  PIPIBoss  阅读(212)  评论(0编辑  收藏  举报