uva 11082Matrix Decompressing

来源:互联网 发布:网络电信诈骗宣传片 编辑:程序博客网 时间:2024/05/17 05:59

原题:
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).
这里写图片描述
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

中文:
给你两个数r和c,表示r行c列的矩阵。然后告诉你前i行矩阵的和以及前j列矩阵的和,问你矩阵当中填数字,填多少满足矩阵的和要求。数字小于20.

#include <bits/stdc++.h>using namespace std;const int inf=999999;const int maxn=60;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 matrix[maxn][maxn];struct EdmondsKarp{    int n,m;    vector<Edge> edges;    vector<int> G[maxn];    int a[maxn];    int p[maxn];    void init(int n)    {        for(int i=0;i<=n;i++)            G[i].clear();        edges.clear();    }    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();        G[from].push_back(m-2);        G[to].push_back(m-1);    }    int Maxflow(int s,int t)    {        int flow=0;        while(true)        {            memset(a,0,sizeof(a));            queue<int> Q;            Q.push(s);            a[s]=INT_MAX;            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(!a[e.to]&&e.cap>e.flow)                    {                        p[e.to]=G[x][i];                        a[e.to]=min(a[x],e.cap-e.flow);                        Q.push(e.to);                    }                }                if(a[t])                    break;            }            if(!a[t])                break;            for(int u=t;u!=s;u=edges[p[u]].from)            {                edges[p[u]].flow+=a[t];                edges[p[u]^1].flow-=a[t];            }            flow+=a[t];        }        return flow;    }};EdmondsKarp EK;int main(){    ios::sync_with_stdio(false);    int t,r,c;    int k=1;    cin>>t;    while(t--)    {        cin>>r>>c;        EK.init(r+c+2);        int pre=0;        for(int i=1;i<=r;i++)        {            int res;            cin>>res;            EK.AddEdge(0,i,res-pre-c);            pre=res;        }        pre=0;        for(int i=1;i<=c;i++)        {            int res;            cin>>res;            EK.AddEdge(r+i,r+c+1,res-pre-r);            pre=res;        }        for(int i=1;i<=r;i++)        {            for(int j=1;j<=c;j++)            {                EK.AddEdge(i,r+j,19);                matrix[i][j]=EK.edges.size()-2;            }        }        EK.Maxflow(0,r+c+1);        cout<<"Matrix "<<k++<<endl;        for(int i=1;i<=r;i++)        {            for(int j=1;j<=c;j++)            {                cout<<EK.edges[matrix[i][j]].flow+1<<" ";            }            cout<<endl;        }        cout<<endl;    }    return 0;}

解答:
紫书上的例题
图论的问题已经要经常敲,否则会生疏。

此问题为限制流量上下界的网络流问题,要求边上的流量大于1小于20.
那么将数值全部减1,就变成了0到19即可。

建图的方式很巧妙,设置Xi为每行的和对应节点,Yj对应每列的和对应的节点。设置源点S和终点T。连接S和Xi,然后连接Yj和终点T,再连接Xi和Yj。
那么Xi到Yj边上的流量就是矩阵[i,j]的值,因为Xi和Yj只相交于一点(i,j)所以这一点(在图中是边)就表示该点在行与列中流量的分配情况。

最后注意结尾有个换行

0 0
原创粉丝点击