【题目大意】
给定一个20*20的矩阵,要求每一列的和是一个定值A[i],每一行是一个定值B[j],求其中的一种方案。
这种方案,所有的数字介于(1-20)之间
【题目分析】
可以行列分开,每一个点代表所在行列的一条弧,流量为1-20,然后源点到每一行有一个容量为和的弧,每一列到汇点也是一个容量为和的值,然后发现这是一个有源点和汇点的最大流,但是由于上下界相同,我们可以统一减去1,跑完网络流之后再加上就可以了。
【代码】
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
#define maxn 2005
#define inf (1e9)
int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int h[maxn],to[maxn],ne[maxn],mp[maxn],f[maxn],en=0;
int tt,n,m,S,T,a[maxn],b[maxn],que[maxn],hd=1,tl=0,ma[50][50];
void add(int a,int b,int r)
{
// printf("add %d to %d is %d\n",a,b,r);
to[en]=b;ne[en]=h[a];f[en]=r;h[a]=en++;
to[en]=a;ne[en]=h[b];f[en]=0;h[b]=en++;
}
bool tell()
{
memset(mp,-1,sizeof mp);
hd=1;tl=0;mp[S]=0;que[++tl]=S;
while (hd<=tl)
{
int x=que[hd++];// printf("%d out of que \n",x);
for (int i=h[x];i>=0;i=ne[i])
{
if (mp[to[i]]==-1&&f[i]>0)
{
mp[to[i]]=mp[x]+1;
que[++tl]=to[i];
}
}
}
if (mp[T]==-1) return false;
else return true;
}
int zeng(int k,int now)
{
if (k==T) return now;
int ret=0;
for (int i=h[k];i>=0;i=ne[i])
{
if (mp[to[i]]==mp[k]+1&&f[i]>0)
{
int tmp=zeng(to[i],min(now-ret,f[i]));
f[i]-=tmp; f[i^1]+=tmp; ret+=tmp;
}
}
if (!ret) mp[k]=-1;
return ret;
}
int main()
{
tt=read();
for (int kas=1;kas<=tt;++kas)
{
n=read();m=read();
S=0;T=maxn-1;
en=0; memset(h,-1,sizeof h);
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
for (int i=1;i<=m;++i) scanf("%d",&b[i]);
for (int i=n;i>=1;--i) a[i]-=a[i-1];
for (int i=m;i>=1;--i) b[i]-=b[i-1];
for (int i=1;i<=n;++i) add(S,i,a[i]-m);
for (int i=1;i<=m;++i) add(i+n,T,b[i]-n);
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
add(i,j+n,19);
while (tell())
{
// printf("can zeng!\n");
while (zeng(S,inf));
}
for (int i=1;i<=n;++i)
for (int j=h[i];j>=0;j=ne[j])
if (to[j]>n&&to[j]<=n+m)
{
// printf("%d to %d %d %d\n",i,to[j]-n,f[j],f[j^1]);
ma[i][to[j]-n]=f[j^1];
}
printf("Matrix %d\n",kas);
for (int i=1;i<=n;++i)
{
for (int j=1;j<=m;++j)
printf("%d ",ma[i][j]+1);
printf("\n");
}
printf("\n");
}
}