题目大意:对于r行c列的正整数矩阵,设Ai为前i行所有元素之和,Bi为前i列所有元素之和,已知R,C和数组A,B,找出满足条件的矩阵,矩阵元素必须是1~20
解题思路:因为元素范围为1~20,所以可以将所有元素减1使得范围变成0~19,并根据Ai,Bi计算出每行,每列的元素和为AAi,BBi
网络流构建:设0为原点s,m+n+1为汇点t,行数为1~m,列数为m+1~m+n
将s与所有行相连,容量为AAi-C,将所有列与t相连,容量为BBi-r,最后将所有行与所有列相连,容量19
求出最大流,最后的x行与y列相连的流量就是(x,y)元素的值
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define INF 0x3f3f3f
#define maxn 100
struct Edge {
int from;
int to;
int cap;
int flow;
Edge(int from, int to, int cap, int flow):from(from),to(to),cap(cap),flow(flow){}
};
int a[maxn];
int b[maxn];
int re[maxn][maxn];
vector<Edge> edges;
vector<int> G[maxn];
int m, n; //m行n列
void addEdge(int from, int to, int cap) {
edges.push_back(Edge(from, to, cap, 0));
edges.push_back(Edge(to, from, 0, 0));
int i = edges.size();
G[from].push_back(i-2);
G[to].push_back(i-1);
}
int EK(int s, int t) {
int visit[maxn];
int flow = 0;
int pre[maxn];
while(1) {
memset(visit, 0, sizeof(visit));
queue<int> que;
que.push(s);
visit[s] = INF;
while(!que.empty()) {
int poi = que.front();
que.pop();
for(int i = 0; i < G[poi].size(); i++) {
Edge& ed = edges[G[poi][i]];
if(!visit[ed.to] && ed.cap > ed.flow) {
que.push(ed.to);
pre[ed.to] = G[poi][i];
visit[ed.to] = min(visit[poi], ed.cap-ed.flow);
}
}
if(visit[t])
break;
}
if(!visit[t])
break;
for(int i = t; i != s; i = edges[pre[i]].from) {
edges[pre[i]].flow += visit[t];
edges[pre[i]^1].flow -= visit[t];
}
flow += visit[t];
}
return flow;
}
void input() {
cin >> m;
cin >> n;
for(int i = 1; i <= m; i++) {
cin >> a[i];;
}
for(int i = 1; i <= n; i++) {
cin >> b[i];
}
for(int i = m; i != 1; i--) {
a[i] = a[i] - a[i-1];
}
for(int i = n; i != 1; i--) {
b[i] = b[i] - b[i-1];
}
}
void init() {
for(int i = 0; i <= m+n+1; i++)
G[i].clear();
edges.clear();
for(int i = 1; i <= m; i++) {
addEdge(0, i, a[i]-n);
}
for(int i = m+1; i <= m+n; i++) {
addEdge(i, m+n+1, b[i-m]-m);
}
for(int i = 1; i <= m; i++) {
for(int j = m+1; j <= m+n; j++) {
addEdge(i, j, 19);
}
}
}
void output(int o) {
EK(0, m+n+1);
cout << "Matrix " << o << endl;
for(int i = 1; i <= m; i++) {
for(int j = m+1; j <= m+n; j++) {
for(int k = 0; k < G[i].size(); k++) {
if(edges[G[i][k]].to == j) {
cout << edges[G[i][k]].flow + 1;
if(j - m != n)
cout << " ";
break;
}
}
}
cout << endl;
}
cout << endl;
}
int main() {
int all;
cin >> all;
for(int i = 1; i <= all; i++) {
input();
init();
output(i);
}
}