Description
sweet和zero在玩矩阵游戏,sweet画了一个N * M的矩阵,矩阵的每个格子有一个整数。zero给出N个数Ki,和M个数Kj,zero要求sweet选出一些数,满足从第 i 行至少选出了Ki个数,第j列至少选出了Kj个数。 这些数之和就是sweet要付给zero的糖果数。sweet想知道他至少要给zero多少个糖果,您能帮他做出一个最优策略吗?
Input
首行一个数T(T <= 40),代表数据总数,接下来有T组数据。
每组数据:
第一行两个数N,M(1 <= N,M <= 50)
接下来N行,每行M个数(范围是0-10000的整数)
接下来一行有N个数Ki,表示第i行至少选Ki个元素(0 <= Ki <= M)
最后一行有M个数Kj,表示第j列至少选Kj个元素(0 <= Kj <= N)
Output
每组数据输出一行,sweet要付给zero的糖果数最少是多少
Sample Input
1 4 4 1 1 1 1 1 10 10 10 1 10 10 10 1 10 10 10 1 1 1 1 1 1 1 1
Sample Output
6
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#define inf 0x3f3f3f3f
#define LL __int64
using namespace std;
const int N = 6000;
int sum,head[N],cost,flow,cnt;
struct node{
int to,c,w,next;
}q[N];
int mp[55][55],cur[N],f[N],dis[N],a1[N/50],a2[N/50];
int st,ed,n;
bool vis[N];
void Add(int u,int v,int cap,int cost){
q[sum].to=v;
q[sum].w=cap;
q[sum].c=cost;
q[sum].next=head[u];
head[u]=sum++;
q[sum].to=u;
q[sum].w=0;
q[sum].c=-cost;
q[sum].next=head[v];
head[v]=sum++;
}
int SPFA(){
memset(vis,false,sizeof(vis));
memset(dis,inf,sizeof(dis));
queue<int>Q;
while(!Q.empty())
Q.pop();
Q.push(st);
cur[st] = -1;
f[st] = inf;
dis[st] = 0;
while(!Q.empty()){
int u = Q.front();
Q.pop();
vis[u] = false;
for(int i = head[u];~i;i=q[i].next ){
int v = q[i].to;
if(dis[v] > dis[u] + q[i].c&&q[i].w ){
dis[v] = dis[u] + q[i].c;
cur[v] = i;
f[v] = min(f[u],q[i].w);
if(!vis[v]){
vis[v] = true;
Q.push(v);
}
}
}
}
if(dis[ed] == inf)
return 0;
flow += f[ed];
cost += f[ed]*dis[ed];
for(int i = cur[ed];~i;i = cur[q[i^1].to ]){
q[i].w -= f[ed];
q[i^1].w += f[ed];
}
return 1;
}
void init(){
memset(head,-1,sizeof(head));
sum = cost = flow = cnt = 0;
}
int main(){
int m,i,j,k,cla;
scanf("%d",&cla);
for(int zu = 1;zu <= cla;++ zu){
init();
scanf("%d%d",&n,&m);
int T = 0;
for( i = 1;i <= n;++ i )
for(j = 1 ;j <= m;++ j){
scanf("%d",&mp[i][j]);
T += mp[i][j];
}
for(i= 1;i <= n;++ i)
scanf("%d",&a1[i]);
for(i= 1;i <= n;++ i)
scanf("%d",&a2[i]);
st = 0;
ed = n+m+11;
for(i = 1;i <= n;++ i ){
Add( st,i,m - a1[i],0 );
Add( i,ed,m - a1[i],0 );
}
for(i = 1;i <= m;++ i ){
Add( n+i,ed,n - a2[i],0 );
}
for(i =1 ;i <= n;++ i)
for(j = 1;j <= m;++ j)
Add(i,n+j,1,-mp[i][j]);
while(SPFA());
printf("%d\n",T + cost);
}
return 0;
}