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 }
  • 相关阅读:
    Redis简单实践-分布式锁
    Redis基础数据结构
    Redis介绍
    MakeGenericType方法,运行时传入泛型T参数,动态生成泛型类
    Visual Studio 2017 Ctrl+单击键会跳转到定义的设置
    10 分钟 创建分布式微服务
    nodejs 中自定义事件
    我是这么给娃娃取名的(使用 node.js )
    使用 Fiddler 上传微信公众账号 自定义菜单
    drf_yasg 简单使用
  • 原文地址:https://www.cnblogs.com/Yuzao/p/6860840.html
Copyright © 2011-2022 走看看