zoukankan      html  css  js  c++  java
  • [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
    ",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 }
  • 相关阅读:
    C++ 单例模式
    单链表快速排序
    美团后台面经
    排序算法及其优化总结
    (转)再谈互斥量与环境变量
    互斥锁和自旋锁
    算法题总结----数组(二分查找)
    Linux里的2>&1的理解
    Ubuntu下开启mysql远程访问
    说说eclipse调优,缩短启动时间
  • 原文地址:https://www.cnblogs.com/Yuzao/p/6860840.html
Copyright © 2011-2022 走看看