UVA

2. B - Matrix Decompressing

题意:定义一个R*C的正整数矩阵(1<=R,C<=20),设Ai为前i行所有元素之和,Bi为前i列所有元素之和。
题目已知R,C和数组A,B。要找一个满足条件的矩阵。矩阵中的元素要满足(1<=X[i][j]<=20)。


思路:

此处输入图片的描述

根据a,b数组求出每一行的元素之和a,每一列的元素之和b 建一个源点s=0,汇点t=R+C+1
然后每一行看成一个顶点1~R,每一列看成一个顶点R+1~R+C
矩阵中每一个位置看成是一条边,比如2行3列的点,就是连接第2行和第3列的点的边。 然后从s到每一行建一条边,容量为a[i],
从每一列到t建一条边,容量为b[i] 然后每一行的点向每一列的点建边,容量为20(暂且说是20,继续看下去,20是错的,19才是对的)
这样的图的意义: 整个矩阵的和代表总的流量 从s出发,分别流向R行(所以有a1+…+a[R]=总流量)
每一行的流量会分给该行的C个元素,每一个列的顶点会从R行获得总的流量,就是该列的流量,最后流到t的总流量还是s出发的流量。
所以行的顶点和列的顶点的R*C条边流过的流量就代表矩阵中R*C个位置的值。
因为题目要求矩阵的位置的值在1~20之间,
所以R*C条边的流量应该在1~20之间,所以R*C条边的最大流量即容量就是20.

但是这样是有问题的,我们好像忽略了一个问题,如果某一条边没有流量怎么办?
某一条边流量为0的情况下,就不能满足矩阵中的元素在1~20之间了
可以先给所有的边给一个值为1的流量,这样的话条件就改成了1~19 了。
求到的最后流量值+1就是矩阵中的元素值。

解决代码:

#include<bits/stdc++.h>
#define maxn 1000
#define INF (1<<31)-1

using namespace std;

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 Dinic
{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    int d[maxn];
    int cur[maxn];
    bool vis[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);
    }

    bool BFS()
    {
        memset(vis,false,sizeof(vis));
        for (int i=0; i<n; i++) d[i] = INF;
        d[s] = 0; vis[s] = true;

        queue<int> Q;
        Q.push(s);
        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] = true;
                    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[e.to] == d[x]+1 && (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;
    }

    bool OKA()
    {
        for (int i=0; i<G[s].size(); i++)
        {
            Edge e = edges[G[s][i]];
            if (e.cap!=e.flow)
                return false;
        }
        return true;
    }

    bool OKB(int R,int C)
    {
        for (int j=R+1; j<=R+C; j++)
        {
            Edge& e = edges[G[j][0]];
            if (e.cap!=e.flow)
                return false;
        }
        return true;
    }

    void Maxflow(int t,int R,int C)
    {
        int flow = 0;
        while (BFS())
        {
            memset(cur,0,sizeof(cur));
            flow += DFS(s,INF);
        }

        cout<<"Matrix "<<t<<endl;
        if (OKA() && OKB(R,C))
        {
            for (int i=1; i<=R; i++)
            {
                int j;
                for (j=1; j<G[i].size()-1; j++)
                    cout<<edges[G[i][j]].flow+1<<' ';
                cout<<edges[G[i][j]].flow+1<<endl;
            }
        }
        cout<<endl;
    }
};

int main()
{
    Dinic aa;
    int T,R,C,tmp;
    int a[30],b[30],c[30],d[30];
 #ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    cin>>T;
    tmp = T;
    while (T>0)
    {
        T--;
        aa.init(maxn);
        cin>>R>>C;
        for (int i=1; i<=R; i++) cin>>a[i];
        for (int i=1; i<=C; i++) cin>>b[i];
        for (int i=1; i<=R; i++) c[i] = a[i]-a[i-1]-C;
        for (int i=1; i<=C; i++) d[i] = b[i]-b[i-1]-R;

        for (int i=1; i<=R; i++)
            aa.Addedge(0,i,c[i]);
        for (int i=1; i<=C; i++)
            aa.Addedge(R+i,R+C+1,d[i]);
        for (int i=1; i<=R; i++)
            for (int j=1; j<=C; j++)
                aa.Addedge(i,R+j,19);
        aa.s = 0; aa.t = R+C+1;
        aa.Maxflow(tmp-T,R,C);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/bryce1010/p/9386888.html