Matrix Decompressing UVA - 11082 (网络流)

传送门

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

题意:首先根据Ai和Bi计算出第i行的元素之和Ai’和第j列的元素之和Bj‘。如果把矩阵里的每个数都减1,则每个Ai’会减少C,而每个Bi‘会减少R。这样一来,每个元素的范围变成了0~19,这样在求解网络流中就不用下限计算了。

建立二分图,每行对应一个X结点,每列对应一个Y结点,然后增加源点s和汇点t,对于每个结点Xi,从s到Xi连一条弧,容量为Ai'-C。从Yi到t连一条狐,容量为Bi'-R。对于每对结点(Xi,Yj),从Xi到Yj连一条弧,容量为19。接下来求s-t的最大流,如果所有s出发到达t都满载,说明问题有解,由于题目保证有解,所以直接输出,结点Xi->Yj的流量就是格子(i,j)减1之后的值。

附上代码:


#include<bits/stdc++.h>

using namespace std;

const int maxn=50+5;
const int inf=0x3f3f3f3f;

struct Edge{
    int from,to,cap,flow;
    Edge(int _from,int _to,int _cap,int _flow):from(_from),to(_to),cap(_cap),flow(_flow){}
};

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;
        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;
    }
};

edmondskarp g;
int no[maxn][maxn];

int main()
{
    int T,R,C,v;
    scanf("%d",&T);
    for(int kase=1;kase<=T;kase++){
        scanf("%d%d",&R,&C);
        g.init(R+C+2);
        int last=0;
        for(int i=1;i<=R;i++){
            scanf("%d",&v);
            g.addedge(0,i,v-last-C);
            last=v;
        }
        last=0;
        for(int i=1;i<=C;i++){
            scanf("%d",&v);
            g.addedge(R+i,R+C+1,v-last-R);
            last=v;
        }
        for(int i=1;i<=R;i++){
            for(int j=1;j<=C;j++){
                g.addedge(i,R+j,19);
                no[i][j]=g.edges.size()-2;
            }
        }
        g.maxflow(0,R+C+1);
        printf("Matrix %d\n",kase);
        for(int i=1;i<=R;i++){
            for(int j=1;j<=C;j++){
                printf("%d ",g.edges[no[i][j]].flow+1);
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/85175490