还是关于网络流的算法题,将每行以及每列之和首先计算出来,然后让矩阵中的每个数字都减少1,那么对于一个R*C的矩阵而言,反应到每行之和就是每行之和都减少C,反应到每列之和就是每列之和都减少R。之所以要减少1也就是便于后面的网络流算法的应用,也就是可以出现边的流量为零的情形。然后建立起始点和终点,起始点到R个点,每条边的容量对应每行之和,建立C个点到终点的边,每一条边的容量也就对应着列之和。然后将R个点以及C个点相互之间建立映射关系,对应的边的容量也就是最大的值19,每一条边其实也就对应着矩阵中的每一个位置,然后利用网络流算法求出最终的结果即可,具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
#include<functional>
using namespace std;
const int Inf = 1 << 20;
class Edge{
public:
int from, to, cap, flow;
};
class Solve{
public:
int R, C;
int A[55],B[55];
vector<Edge> edge;
vector<int> G[100];
int ID[55][55];
void addEdge(int from,int to,int cap){
Edge temp;
temp.from = from, temp.to = to, temp.cap = cap, temp.flow = 0;
edge.push_back(temp);
Edge temp2;
temp2.from = to, temp2.to = from, temp2.cap = 0, temp2.flow = 0;
edge.push_back(temp2);
int t = edge.size();
G[from].push_back(t-2);
G[to].push_back(t - 1);
}
void MaxFlow(int start,int e){
while (true){
int d[100];
int parent[100];
memset(d, 0, sizeof(d));
d[start] = Inf;
queue<int> q;
q.push(start);
while (!q.empty()){
int id = q.front();
q.pop();
for (int i = 0; i < G[id].size(); i++){
int ide = G[id][i];
int to = edge[ide].to;
if (!d[to]&&edge[ide].cap > edge[ide].flow){
d[to] = min(d[id], edge[ide].cap - edge[ide].flow);
parent[to] = ide;
q.push(to);
}
}
if (d[e]) break;
}
if (!d[e]) break;
for (int i = e; i != start; i = edge[parent[i]].from){
edge[parent[i]].flow += d[e];
edge[parent[i] ^ 1].flow -= d[e];
}
}
}
void Init(){
edge.clear();
memset(ID,0,sizeof(ID));
for (int i = 0; i < 100; i++) G[i].clear();
cin >> R >> C;
for (int i = 0; i < R; i++) cin >> A[i];
for (int i = 0; i < C; i++) cin >> B[i];
for (int i = R - 1; i > 0; i--){
A[i] = A[i] - A[i - 1] - C;
}
A[0] -= C;
for (int i = C - 1; i > 0; i--){
B[i] = B[i] - B[i - 1] - R;
}
B[0] -= R;
for (int i = 0; i < R; i++){
addEdge(0,i+1,A[i]);
}
for (int i = R + 1; i <= R + C; i++){
addEdge(i, R + C + 1, B[i - R - 1]);
}
for (int i = 1; i <= R; i++){
for (int j = 1; j <= C; j++){
addEdge(i, j + R, 19);
ID[i][j] = edge.size() - 2;
}
}
}
void Deal(){
Init();
MaxFlow(0,R+C+1);
for (int i = 1; i <= R; i++){
for (int j = 1; j <= C; j++){
int ind = ID[i][j];
cout << edge[ind].flow + 1<<" ";
}
cout << endl;
}
}
};
int main(){
int T;
cin >> T;
Solve a;
for (int i = 0; i < T;i++){
cout << "Matrix " << i + 1 << endl;
a.Deal();
cout << endl;
}
return 0;
}