Matrix Decompressing UVA - 11082

还是关于网络流的算法题,将每行以及每列之和首先计算出来,然后让矩阵中的每个数字都减少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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值