【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\n",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\n",sum);
120     return 0;
121 }
View Code

 

2017-04-07 16:26:33

posted @ 2017-04-07 16:26  konjak魔芋  阅读(186)  评论(0编辑  收藏  举报