• 【BZOJ 3442】 3442: 学习小组 (最大费用流)


    3442: 学习小组

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 403  Solved: 193

    Description

    【背景】
    坑校准备鼓励学生参加学习小组。
    【描述】
        共有n个学生,m个学习小组,每个学生有一定的喜好,只愿意参加其中的一些学习小组,但是校领导为学生考虑,规定一个学生最多参加k个学习小组。财务处的大叔就没那么好了,他想尽量多收钱,因为每个学生参加学习小组都要交一定的手续费,不同的学习小组有不同的手续费。然而,事与愿违,校领导又决定对学习小组组织者进行奖励,若有a个学生参加第i个学习小组,那么给这个学习小组组织者奖励Ci*a^2元。在参与学生(而不是每个学习小组的人数总和)尽量多的情况下,求财务处最少要支出多少钱(若为负数,则输出负数)(支出=总奖励费-总手续费)。

    Input

    输入有若干行,第一行有三个用空格隔开的正整数n、m、k。接下来的一行有m个正整数,表示每个Ci。第三行有m个正整数,表示参加每个学习小组需要交的手续费Fi。再接下来有一个n行m列的矩阵,表若第i行j列的数字是1,则表示第i个学生愿意参加第j个学习小组,若为0,则为不愿意。

    Output

    输出只有一个整数,为最小的支出。

    Sample Input


    3 3 1
    1 2 3
    3 2 1
    111
    111
    111

    Sample Output


    -2
    【样例解释】
    参与学生最多为3,每个学生参加一个学习小组,若有两个学生参加第一个学习小组,一个学生参加第二个学习小组(一定要有人参加第二个学习小组),支出为-2,可以证明没有更优的方案了。
    【数据范围与约定】
    100%的数据,0<n≤100,0<m≤90,0<k≤m,0<Ci≤10,0<Fi≤100。

    HINT

    Source

    【分析】

     转自:http://blog.csdn.net/Vmurder/article/details/43057197

    今天有点傻,不想打题解了。。自己看吧。。。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 #define Maxn 110
      9 #define INF 0x7fffffff
     10 
     11 int mymin(int x,int y) {return x<y?x:y;}
     12 
     13 int c[Maxn];
     14 
     15 struct node
     16 {
     17     int x,y,f,c,o,next;
     18 }t[Maxn*Maxn*30];
     19 int len,first[Maxn*2];
     20 
     21 void ins(int x,int y,int f,int c)
     22 {
     23     // swap(x,y);
     24     t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c;
     25     t[len].next=first[x];first[x]=len;t[len].o=len+1;
     26     t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c;
     27     t[len].next=first[y];first[y]=len;t[len].o=len-1;
     28 }
     29 
     30 queue<int > q;
     31 int st,ed;
     32 int flow[Maxn*2],pre[Maxn*2],dis[Maxn*2];
     33 bool inq[Maxn*2];
     34 bool bfs()
     35 {
     36     while(!q.empty()) q.pop();
     37     for(int i=1;i<=ed;i++) dis[i]=INF;
     38     memset(inq,0,sizeof(inq));
     39     flow[st]=INF;q.push(st);dis[st]=0;
     40     inq[st]=1;
     41     while(!q.empty())
     42     {
     43         int x=q.front();
     44         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     45         {
     46             int y=t[i].y;
     47             if(dis[y]>dis[x]+t[i].c)
     48             {
     49                 dis[y]=dis[x]+t[i].c;
     50                 pre[y]=i;
     51                 flow[y]=mymin(flow[x],t[i].f);
     52                 if(!inq[y])
     53                 {
     54                     q.push(y);
     55                     inq[y]=1;
     56                 }
     57             }
     58         }
     59         q.pop();inq[x]=0;
     60     }
     61     if(dis[ed]==INF) return 0;
     62     return 1;
     63 }
     64 
     65 int sum=0;
     66 int max_flow()
     67 {
     68     while(bfs())
     69     {
     70         int x=ed;
     71         sum+=flow[ed]*dis[ed];
     72         int a=flow[ed];
     73         while(x!=st)
     74         {
     75             t[pre[x]].f-=a;
     76             t[t[pre[x]].o].f+=a;
     77             x=t[pre[x]].x;
     78         }
     79     }
     80 }
     81 
     82 void output()
     83 {
     84     for(int i=1;i<=len;i+=2)
     85      printf("%d -> %d %d %d
    ",t[i].x,t[i].y,t[i].f,t[i].c);
     86 }
     87 
     88 char s[Maxn];
     89 
     90 int main()
     91 {
     92     int n,m,k;
     93     scanf("%d%d%d",&n,&m,&k);
     94     st=n+m+1;ed=st+1;
     95     for(int i=1;i<=m;i++)
     96     {
     97         int cc;
     98         scanf("%d",&cc);
     99         for(int j=1;j<=n;j++)
    100         {
    101             ins(st,i,1,cc*(2*j-1));
    102         }
    103     }
    104     for(int i=1;i<=m;i++) scanf("%d",&c[i]);
    105     for(int i=1;i<=n;i++) ins(st,i+m,k-1,0);
    106     for(int i=1;i<=n;i++)
    107     {
    108         scanf("%s",s+1);
    109         for(int j=1;j<=m;j++)
    110          {
    111              if(s[j]=='1') ins(j,m+i,1,-c[j]);
    112          }
    113     }
    114      
    115     for(int i=1;i<=n;i++) ins(m+i,ed,k,0);
    116     // output();
    117     // swap(st,ed);
    118     sum=0;max_flow();
    119     printf("%d
    ",sum);
    120     return 0;
    121 }
    View Code

    2017-04-07 16:26:33

  • 相关阅读:
    SNMP简介
    命令模式
    牛顿法
    仿射函数
    schedule
    命令模式
    牛顿法
    schedule
    仿射函数
    适配器模式
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6678776.html
Copyright © 2020-2023  润新知