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
",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
",cas);
        ek.n = n, ek.m = m;
        ek.getMatrix();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xiaochaoqun/p/7190016.html