UVA11082 Matrix Decompressing 最大流建模解矩阵,经典

/**
题目:UVA11082 Matrix Decompressing
链接:https://vjudge.net/problem/UVA-11082
题意:lrj入门经典P374
已知一个矩阵的行数为r,列数为c,前i行的和ai(1<=i<=r),前j列的和bj(1<=j<=c)。
ai,bj都在[1,20]内。求出这个矩阵。

思路:通过前i行的和以及前j列的和,获得每一行的和以及每一列的和。

把每一行看做一个节点,每一列看做一个节点。
建立一个源点到达每一行。
建立一个汇点,每一列到达汇点。
每一行到达每一列。

由于数据范围是[1,20]。流可以说0.所以为了方便处理,所有容量-1.最后结果+1.
那么源点到第i行的容量为r[i]-列数。(每一行有列数个数)
第j列到汇点的容量为c[j]-行数。
第i行到第j列的容量都为19。(20-1)

每一行都经过每一列组成。所以这样建立连接。

如果源点到每一个行节点都是满载。
每一个列节点到汇点都是满载。
那么有解。

解为:
第i行第j列的元素为第i行的节点到第j列的节点的流+1。

*/
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int N = 110;
int r[N], c[N];
struct Edge{
    int from, to, cap, flow;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct EdmondsKarp
{
    int n, m;
    vector<Edge> edges;
    vector<int> G[N];
    int p[N];
    int a[N];
    int ans[N][N];

    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;
        for(;;){
            memset(a, 0, sizeof a);
            queue<int>Q;
            Q.push(s);
            a[s] = INF;
            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;
    }

    void getMatrix()
    {
        int r = 0, c = 0;
        for(int i = 2*(n+m); i < edges.size(); i+=2){
            if(c==m) {
                r++, c = 0;
            }
            ans[r][c] = edges[i].flow;
            c++;
        }
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(j==m-1) printf("%d\n",ans[i][j]+1);
                else printf("%d ",ans[i][j]+1);
            }
        }
    }
};

int main()
{
    int n, m, T;
    scanf("%d",&T);
    for(int cas = 1; cas <= T; cas++){
        scanf("%d%d",&n,&m);
        for(int i = 0; i < n; i++) scanf("%d",&r[i]);
        for(int i = 0; i < m; i++) scanf("%d",&c[i]);
        for(int i = n-1; i > 0; i--) r[i] = r[i]-r[i-1];
        for(int i = m-1; i > 0; i--) c[i] = c[i]-c[i-1];
        int s, t;
        s = 0, t = n+m+1;
        EdmondsKarp ek;
        ek.init(t);
        ///s -> r
        for(int i = 0; i < n; i++) ek.AddEdge(s,i+1,r[i]-m);
        ///c -> t
        for(int i = 0; i < m; i++) ek.AddEdge(n+i+1,t,c[i]-n);
        ///r -> c
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                ek.AddEdge(i+1,n+j+1,19);
            }
        }
        int flow = ek.Maxflow(s,t);
        printf("Matrix %d\n",cas);
        ek.n = n, ek.m = m;
        ek.getMatrix();
    }
    return 0;
}
时间: 2024-08-08 11:06:56

UVA11082 Matrix Decompressing 最大流建模解矩阵,经典的相关文章

UVA-11082 Matrix Decompressing (网络流建模)

题目大意:给出一个由1到20组成的整数矩阵的每一行和每一列的和,构造这个矩阵.输出任意一个构造方案. 题目分析:将每一行视作一个点x,将每一列视作一个点y.对于矩阵中的每一个格子,都对应一个二元关系<x,y>,从x连一条有向弧到y,容量置为19.增加源点s和汇点t,对于每一个x,连一条从s到x的有向弧,容量置为对应的该行总和减去列数,对于每一个y,连一条从y到t的有向弧,容量置为对应的该列总和减去行数.对于这个寻找最大流,算法终止后,如果从s出发的每一条弧和到达t的每一条弧都是饱和的,那么每一

UVA-11082 Matrix Decompressing(有上下界的最大流)

题目链接: Matrix Decompressing 题意: 给一个矩阵的每行和每列的和,(给的是前i行或者列的和); 矩阵中每个元素的值在1到20之间,找出这样的一个矩阵: 思路: 把它转化成一个二分图,每行和每列之间连一条弧,然后设置一个源点和一个汇点,源点与行点相连,汇点与列点相连,求一个最大值,当然这是一个有下界的最大流,需要做-1的处理,同时与源汇相连的边也是要处理的;最后求得的反向边+1就是答案了; AC代码: #include <bits/stdc++.h> /*#include

UVa 11082 Matrix Decompressing(最大流)

不想吐槽了..sample input 和sample output 完全对不上...调了一个晚上...不想说什么了... ------------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vect

UVa11082 Matrix Decompressing(最小费用最大流)

题目大概有一个n*m的矩阵,已知各行所有数的和的前缀和和各列所有数的和的前缀和,且矩阵各个数都在1到20的范围内,求该矩阵的一个可能的情况. POJ2396的弱化版本吧..建图的关键在于: 把行.列看成点,各单元看成边 这个建图感觉非常巧.. 各个单元有下界限制..这个我可不想再写带下界的最大流.. 想了下,发现可以用最小费用最大流求解:通过放大边的费用,使得这条边成为一条必须会被经过的边. 简单来说就是各单元代表的边拆成两条,一条容量1费用-1,另外一条容量19费用0.这样跑MCMF,显然为了

11082 - Matrix Decompressing (网络流建模|二分图匹配)

该题是一道经典的二分图匹配的题目 .现在终于有点明白什么是二分图匹配了,其实说白了就是依赖于最大流算法之上的一种解决特定问题的算法 . 所谓二分图,就是我们假定有两个集合A和B,每个集合中有若干元素(点),其中源点与A相连,汇点与B相连,并且他们的总容量决定了最终答案的上限,所以一定要维护好 . 然后由A中的点向B中的点连线,他们之间也有一定的容量制约关系(具体看题目中的边权值限制).这样就可以求出最大流量匹配了. 有时我们要求完美匹配,即所有流入的量等于流出的量  . 该题构思极其巧妙,因为我

uva11082 Matrix Decompressing

网络流 首先算出每行每列的数的和. 每行的值减去c,每列的值减去R 然后每行和每列之间连边,容量为19. 这样一来,(i,j)的流量相当于(i,j)的值-1. 这样就避免了流量为0不对应答案的尴尬情况. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 1000 + 10; const int maxm = 100000 + 10; c

[题解]UVa 11082 Matrix Decompressing

开始眨眼一看怎么也不像是网络流的一道题,再怎么看也觉得像是搜索.不过虽然这道题数据范围很小,但也不至于搜索也是可以随随便便就可以过的.(不过这道题应该是special judge,因为一题可以多解而且题目中然而并没有什么要求,所以说可以考虑思考一下这道题有木有什么"套路"之类的通法) 比如说有这么一组数据 原矩阵 1 2 3 4 7 8 9 5 6 输入 3 3 6 25 45 14 28 45 然后将每一行的和写在每一列对应的行上(很明显有问题) 6 0 0 19 0 0 20 0

uva Matrix Decompressing (行列模型)

Matrix Decompressing 题目:    给出一个矩阵的前i行,前j列的和.要求你求出满足的矩阵.矩阵的数范围在[1,20].   一开始就坑在了这里.没读仔细题目.囧...   其实这题的模型就是一个网络流的行列模型,跟poj的那题budge一样建图.不过Poj 的那个建图输入麻烦,而这题是裸的,因为已经告诉你了下界为1,上界为20,囧...而且poj那题我至今也不知道为什么我会一直超时.T_T 算法:    行列模型可以转换成网络流的有源汇上下界网络流求解.而行号和列号分别作为

最小费用最大流粗解 poj2516

最小费用最大流,一般解法如下: 在流量基础上,每条边还有权费用,即单位流量下的所需费用.在最大流量下,求最小费用.解法:在最大流算法基础上,每次按可行流增广改为每次用spfa按最小费用(用单位费用)增广,每次按每条边一单位费用求到达终点的最小费用(最短路),那么每次找到"最短路"(只是一条路,不是多条(dinic每次可以增广多条)),之后按这条路最大 可能流量增广(取这条路上残量最小的),直到无法增广为止.(实现细节点代码备注). 该题题意:m个供应地向n个商店供应k种物品,对于每种物