UVA 11082 Matrix Decompressing(网络流)

题意:给一个R行C列的正整数矩阵,设Ai为前i行所有元素之和,Bi为前i列所有元素之和,已知R和C,和数组A,B,找一个满足条件的矩阵,矩阵中所有元素必须是1到20的正整数。

思路:万万想不到是用网络流来做...首先根据Ai和Bi计算出第i行的元素之和和第i列的元素之和,如果把矩阵里面的每个数减去一,则每个Ai'会减少C,同理Bi‘减少R,则每个元素的范围变成了0-19.为什么要这样做呢,因为网络流里面是可能存在0流的,所以我们把下界减一,那么答案就不会有漏。然后建图的话参照紫书吧


#include<bits/stdc++.h>
using namespace std;
#define INF 1e9
const int maxn = 1000;
struct Edge
{
	int from,to,cap,flow;
	Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
int id[50][50];
int r,c,a[25],b[25];
struct Dinic
{
	int n,m,s,t;
	vector<Edge>edges;
	vector<int> G[maxn];
	bool vis[maxn];
	int d[maxn];
	int cur[maxn];
	void AddEdge(int from,int to,int cap)
	{
		edges.push_back(Edge(from,to,cap,0));
		edges.push_back(Edge(to,from,0,0));
		m = edges.size();
		id[from][to]=m-2;
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}
	void init(int n)
	{
		for (int i = 0;i<=n;i++)
			G[i].clear();
		edges.clear();
		a[0]=b[0]=0;
	}
	bool BFS()
	{
		memset(vis,0,sizeof(vis));
		queue<int>q;
		q.push(s);
		d[s]=0;
		vis[s]=1;
		while (!q.empty())
		{
			int x = q.front();
			q.pop();
			for (int i = 0;i<G[x].size();i++){
				Edge &e = edges[G[x][i]];
				if (!vis[e.to] && e.cap>e.flow){
					vis[e.to]=1;
					d[e.to]=d[x]+1;
					q.push(e.to);
				}
			}
		}
		return vis[t];
	}

	int DFS(int x,int a){
		if (x==t || a==0)
			return a;
		int flow = 0,f;
		for (int &i=cur[x];i<G[x].size();i++){
			Edge&e = edges[G[x][i]];
			if (d[x]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0){
				e.flow+=f;
				edges[G[x][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if (a==0)
					break;
			}
		}
		return flow;
	}

	int Maxflow(int s,int t)
	{
		this->s=s;
		this->t=t;
		int flow = 0;
		while (BFS())
		{
			memset(cur,0,sizeof(cur));
			flow+=DFS(s,INF);
		}
		return flow;
	}
}di;
int main()
{
   int T;
   scanf("%d",&T);
   int cas=1;
   while (T--)
   {
	   scanf("%d%d",&r,&c);
       di.init(r+c+2);
	   for (int i = 1;i<=r;i++)
		   scanf("%d",&a[i]);
	   for (int i = 1;i<=c;i++)
		   scanf("%d",&b[i]);
	   for (int i = 1;i<=r;i++)
		   di.AddEdge(0,i,a[i]-a[i-1]-c);
	   for (int i = 1;i<=r;i++)
		   for (int j = r+1;j<=r+c;j++)
			   di.AddEdge(i,j,19);
	   for (int i = r+1;i<=r+c;i++)
		   di.AddEdge(i,r+c+1,b[i-r]-b[i-r-1]-r);
	   di.Maxflow(0,r+c+1);
	   printf("Matrix %d\n",cas++);
	   for (int i = 1;i<=r;i++)
		   for (int j = 1;j<=c;j++)
			   printf("%d%c",di.edges[id[i][j+r]].flow+1,(j==c)?'\n':' ');
	   if (T)
		   printf("\n");
   }
}




Some R × C matrix of positive integers is encoded and represented by its R cumulative row sum and
C column sum entries. Given, R, C and those R + C cumulative row sum and column sums, you want
to decode the matrix (i.e., find all the individual R ∗ C entries).
Here,
RowSum(i) = ∑
C
j=1
Aij
CumulativeRowSum(i) = ∑
i
k=1

C
j=1
Akj
ColumnSum(i) = ∑
R
j=1
Aji
CumulativeColumnSum(i) = ∑
i
k=1

R
j=1
Ajk
Or in other words, the i-th row sum is the sum of all the entries in row i. And the cumulative i-th
row sum is the sum of all the row sums from row 1 to row i (inclusive).
Input
There can be multiple test cases. The first line of input contains the number of test cases, T (1 ≤ T ≤
100). Each test case contains 3 lines of input. The first line of the test case gives the size of the matrix:
the number of rows, R (1 ≤ R ≤ 20) and the number of columns C (1 ≤ C ≤ 20). The next line
contains all the R cumulative row sums, and the last line of the test case contains the C cumulative
column sums. Any two successive numbers in the same line is separated by a single space.
Output
For each test case print the label of the test case in the first line. The format of this label should be
“Matrix x” where x would be replaced by the serial number of the test case starting at 1. In each of
the following R lines print C integers giving all the individual entries of the matrix. You can assume
that there is at least one solution for each of the given encodings. To simplify the problem further,
we add the constraint that each entry in the matrix must be an integer between 1 and 20. In case of
multiple solutions, you can output any one of them.

Sample Input
2
3 4
10 31 58
10 20 37 58
3 4
10 31 58
10 20 37 58
Sample Output
Matrix 1
1 6 1 2
1 2 2 16
8 2 14 3
Matrix 2
1 1 1 7
1 1 7 12

8 8 9 2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值