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

题目大意:给出一个由1到20组成的整数矩阵的每一行和每一列的和,构造这个矩阵。输出任意一个构造方案。

题目分析:将每一行视作一个点x,将每一列视作一个点y。对于矩阵中的每一个格子,都对应一个二元关系<x,y>,从x连一条有向弧到y,容量置为19。增加源点s和汇点t,对于每一个x,连一条从s到x的有向弧,容量置为对应的该行总和减去列数,对于每一个y,连一条从y到t的有向弧,容量置为对应的该列总和减去行数。对于这个寻找最大流,算法终止后,如果从s出发的每一条弧和到达t的每一条弧都是饱和的,那么每一个xi到yj的流量便是对应格子中的值减一;否则,无解。这道题,一定有解。  显然,这样建模是正确的。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<cmath>
# include<string>
# include<vector>
# include<list>
# include<set>
# include<map>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

# define LL long long
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a))
# define CLL(a,b,n) fill(a,a+n,b)

const double inf=1e30;
const int INF=1<<30;
const int N=1000;

struct Edge
{
    int fr,to,cap,flow;
    Edge(int _fr,int _to,int _cap,int _flow):fr(_fr),to(_to),cap(_cap),flow(_flow){}
};
vector<Edge>edge;
int id[50][50],r,c,a[25],b[25],f[50],p[50];
vector<int>G[50];

void init()
{
    a[0]=b[0]=0;
    REP(i,0,r+c+2) G[i].clear();
    edge.clear();
}

void addEdge(int fr,int to,int cap)
{
    edge.push_back(Edge(fr,to,cap,0));
    edge.push_back(Edge(to,fr,0,0));
    int m=edge.size();
    id[fr][to]=m-2;
    G[fr].push_back(m-2);
    G[to].push_back(m-1);
}

void maxFlow(int s,int t)
{
    while(1)
    {
        queue<int>q;
        CL(f,0);
        f[s]=INF;
        q.push(s);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            REP(i,0,G[u].size()){
                Edge &e=edge[G[u][i]];
                if(!f[e.to]&&e.cap>e.flow){
                    p[e.to]=G[u][i];
                    f[e.to]=min(f[u],e.cap-e.flow);
                    q.push(e.to);
                }
            }
            if(f[t]) break;
        }
        if(!f[t]) break;
        for(int u=t;u!=s;u=edge[p[u]].fr){
            edge[p[u]].flow+=f[t];
            edge[p[u]^1].flow-=f[t];
        }
    }
}

int main()
{
    int T,cas=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&r,&c);
        init();
        REP(i,1,r+1) scanf("%d",a+i);
        REP(i,1,c+1) scanf("%d",b+i);
        REP(i,1,r+1) addEdge(0,i,a[i]-a[i-1]-c);
        REP(i,1,r+1) REP(j,r+1,r+c+1) addEdge(i,j,19);
        REP(i,r+1,r+c+1) addEdge(i,r+c+1,b[i-r]-b[i-r-1]-r);
        maxFlow(0,r+c+1);
        printf("Matrix %d\n",++cas);
        REP(i,1,r+1) REP(j,1,c+1) printf("%d%c",edge[id[i][j+r]].flow+1,(j==c)?'\n':' ');
        if(T) printf("\n");
    }
  return 0;
}

  

posted @ 2015-12-01 23:19  20143605  阅读(273)  评论(0编辑  收藏  举报