一道很基础的网络流建模。。
本题输入的是前缀和,先用它们求出每行、每列的元素和
然后将每一行看作一个节点(记作Xi),每一列看作一个节点(记作Yi),并新增源点S、汇点T。
S往Xi连边,容量为这一行的元素和减1;
Yi往T连边,容量同上。
每个Xi往每个Yj连边,容量为20-1=19。
之所以要将容量都减1,是因为边权要在1~20之间,有下界,但并不需要用到专门的有下界最大流算法,可以直接先减1,求出结果后再加1。
跑一遍最大流。当且仅当所有S出边和T入边都满载时有解。元素Aij的值即为Xi -> Yj的流量+1。
模板用的是Rujia Liu的。。可读性很强,但效率不是很高。。下次把黄学长的模板学过来。。
(最近刷题速度下降。。再这样下去药丸。。
// UVa11082
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int M=2000, N=100, INF=0x3f3f3f3f;
#define rep(i,a,b) for (int i=a; i<=b; i++)
#define read(x) scanf("%d", &x)
struct Edge{
int from, to, pre, cap, flow;
}e[M];
int p, pre[N];
void ine(int from, int to, int cap, int flow) {
e[p].from=from; e[p].to=to; e[p].cap=cap; e[p].pre=pre[from]; e[p].flow=flow; pre[from]=p;
p++;
}
#define reg(i,x) for (int i=pre[x]; i!=-1; i=e[i].pre)
void Add_Edge(int from, int to, int cap) {
ine(from, to, cap, 0);
ine(to, from, 0, 0);
}
int n, m, s, t, a[N], last, tot, edges, nodes, id[N][N], kase=0, T, cur[N], d[N];
bool vis[N];
void init() {
p=0;
rep(i,1,edges) e[i].pre=-1;
rep(i,1,nodes) pre[i]=-1;
}
int Q[2*N];
bool BFS() {
memset(vis, 0, sizeof(vis));
int head=1, tail=1;
Q[1]=s; d[s]=0; vis[s]=true;
while (head<=tail) {
int x=Q[head++];
reg(i,x) {
int y=e[i].to;
if (!vis[y] && e[i].cap>e[i].flow) {
vis[y]=true;
d[y]=d[x]+1;
Q[++tail]=y;
}
}
}
return vis[t];
}
int DFS(int x, int a) { // a表示“目前为止所有弧的最小残量”
if (x==t || a==0) return a;
int flow=0, f;
for (int &i=cur[x]; i!=-1; i=e[i].pre) {
if (d[x]+1==d[e[i].to] && (f=DFS(e[i].to, min(a, e[i].cap-e[i].flow)))>0) {
flow+=f;
a-=f; // Why can we do this?
e[i].flow+=f;
e[i^1].flow-=f;
if (a==0) break;
}
}
return flow;
}
void Dinic() {
int flow=0;
while (BFS()) {
rep(i,1,n+m+2) cur[i]=pre[i];
flow+=DFS(s, INF);
}
}
int main()
{
read(T);
while (T--) {
read(n); read(m);
edges=n*m*2+n+m+5;
nodes=n+m+5;
init();
read(tot); a[1]=tot;
rep(i,2,n) last=tot, read(tot), a[i]=tot-last;
read(tot); a[n+1]=tot;
rep(i,n+2,n+m) last=tot, read(tot), a[i]=tot-last;
s=n+m+1, t=n+m+2;
rep(i,1,n) Add_Edge(s, i, a[i]-m);
rep(i,n+1,m+n) Add_Edge(i, t, a[i]-n);
rep(i,1,n)
rep(j,n+1,n+m) {
Add_Edge(i, j, 19);
id[i][j]=p-2;
}
Dinic();
printf("Matrix %d\n", ++kase);
rep(i,1,n) {
rep(j,n+1,n+m)
printf("%d ", e[id[i][j]].flow+1);
puts("");
}
puts("");
}
return 0;
}