【BZOJ 3442】 3442: 学习小组 (最大费用流)
3442: 学习小组
Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 403 Solved: 193Description
【背景】坑校准备鼓励学生参加学习小组。【描述】共有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 }
2017-04-07 16:26:33