How to earn more
My Tags | (Edit) |
---|
Source : ww | |||
Time limit : 1 sec | Memory limit : 64 M |
Submitted : 381, Accepted : 217
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 ithnumber 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.
题意:
有m个项目,n个员工,每个项目可以得到一些收益,每个员工需要给付一些工资,每个项目对应若干个员工,每个员工可以参加多个项目,求出最大收益。
分析:
这道题可以转化为最大权闭合子图,项目看成权值为正的点,员工看成权值为负的点,每个项目对应若干个员工也就是说如果要选择这个项目就必须要选择这些员工,也就是项目向员工连边,出边必须在点集中,然后求最小割就好了...
代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 //by NeighThorn 6 #define inf 0x3f3f3f3f 7 using namespace std; 8 9 const int maxn=200+2+5,maxm=40000+5; 10 11 int cas,m,n,ans; 12 int hd[maxn],fl[maxm],to[maxm],nxt[maxm],pos[maxn],S,T,cnt; 13 14 inline int read(void){ 15 char ch=getchar();int x=0; 16 while(!(ch>=‘0‘&&ch<=‘9‘)) 17 ch=getchar(); 18 while(ch>=‘0‘&&ch<=‘9‘) 19 x=x*10+ch-‘0‘,ch=getchar(); 20 return x; 21 } 22 23 inline void add(int s,int x,int y){ 24 fl[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++; 25 fl[cnt]=0;to[cnt]=x;nxt[cnt]=hd[y];hd[y]=cnt++; 26 } 27 28 inline bool bfs(void){ 29 memset(pos,-1,sizeof(pos)); 30 int q[maxn],head=0,tail=0; 31 q[0]=S,pos[S]=0; 32 while(head<=tail){ 33 int top=q[head++]; 34 for(int i=hd[top];i!=-1;i=nxt[i]) 35 if(pos[to[i]]==-1&&fl[i]) 36 pos[to[i]]=pos[top]+1,q[++tail]=to[i]; 37 } 38 return pos[T]!=-1; 39 } 40 41 inline int find(int v,int f){ 42 if(v==T) 43 return f; 44 int res=0,t; 45 for(int i=hd[v];i!=-1&&res<f;i=nxt[i]) 46 if(pos[to[i]]==pos[v]+1&&fl[i]) 47 t=find(to[i],min(f-res,fl[i])),res+=t,fl[i]-=t,fl[i^1]+=t; 48 if(!res) 49 pos[v]=-1; 50 return res; 51 } 52 53 inline int dinic(void){ 54 int res=0,t; 55 while(bfs()) 56 while(t=find(S,inf)) 57 res+=t; 58 return res; 59 } 60 61 signed main(void){ 62 cas=read(); 63 while(cas--){ 64 memset(hd,-1,sizeof(hd)); 65 ans=cnt=0;m=read(),n=read(),S=0,T=m+n+1; 66 for(int i=1,x;i<=m;i++) 67 x=read(),ans+=x,add(x,S,i); 68 for(int i=1,x;i<=n;i++) 69 x=read(),add(x,i+m,T); 70 for(int i=1,num;i<=m;i++){ 71 num=read(); 72 for(int j=1,x;j<=num;j++) 73 x=read(),x++,add(inf,i,x+m); 74 } 75 ans=ans-dinic();printf("%d\n",ans); 76 } 77 return 0; 78 }
by NeighThorn