Matrix Decompressing UVA

来源:互联网 发布:les小说软件 编辑:程序博客网 时间:2024/06/07 03:02

Matrix Decompressing UVA - 11082

网络流·最大流

http://m.blog.csdn.net/article/details?id=46985575

题目大意:

给出一个矩阵前i列所有元素的和,和前j行所有元素的和,求这个矩阵解压以后的原型。(答案不唯一)

题解:

先根据题目所给出的条件,求出每行每列的和。然后把每行每列都当成一个节点,设置一个超级源点连向所有行结点,容量为“该行的和减去列数”,设置一个超级汇点,使所有的列结点连向超级汇点,容量为“该列的和减去行数”,然后所有的行结点和列结点相连,容量为19。图建好了,之后求完最大流,行结点列结点对应边上的流量,就是解压后的矩阵的元素。
那么这里有一个问题,为什么上面的容量要设置成“该列的和减去行数”和“该行的和减去列数”还有“19”,是不是都少了什么?在建图之前,把矩阵中的每一个元素都减去1,所以每列减去了行数,每行减去列数。这样做的目的是为了保证最终矩阵中的每一个元素都在1~20之内。如果不作处理的话,会出现0流,不符合题目条件。所以在一开始全部减去一,流不会为负,最后输出的时候在全部都加上一,就符合了题目的条件。

Code:

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#define D(x) cout<<#x<<" = "<<x<<"  "#define E cout<<endlusing namespace std;const int N = 55;const int M = N*N+2*N;const int INF = 0x3f3f3f3f;int n,m,S,T;int hang[N], lie[N], tp[N];struct edge{    int to,cap,flow,next;}e[M*2];int head[N*2],ec=1;void clear(){ memset(head,0,sizeof(head)); ec=1; }void add(int a,int b,int cap){    ec++; e[ec].to=b; e[ec].cap=cap; e[ec].flow=0;    e[ec].next=head[a]; head[a]=ec;}void add2(int a,int b,int cap){//  D(a); D(b); D(cap); E;    add(a,b,cap); add(b,a,0);}bool vis[N*2]; int d[N*2];bool bfs(){    memset(vis,false,sizeof(vis));    queue<int> q; q.push(S); vis[S]=true; d[S]=0;    while(!q.empty()){        int u=q.front(); q.pop();        for(int i=head[u];i;i=e[i].next){            int v=e[i].to;            if(!vis[v] && e[i].cap>e[i].flow){                d[v]=d[u]+1; vis[v]=true;                q.push(v);                if(v==T) return true;               }        }    }    return false;}int dfs(int u,int a){    if(u==T || a==0) return a;    int flow=0, f;    for(int i=head[u];i;i=e[i].next){        int v=e[i].to;        if(d[v]==d[u]+1 && (f=dfs(v,min(a,e[i].cap-e[i].flow)))){            flow+=f; a-=f;            e[i].flow+=f; e[i^1].flow-=f;            if(a==0) break;        }    }    if(a) d[u]=-1;    return flow;}int mxf(){    int flow=0;    while(bfs()){        flow+=dfs(S,INF);    }    return flow;}void build(){    clear();    S=n+m+1; T=S+1;    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            add2(i,j+n,19);    for(int i=1;i<=n;i++)         add2(S,i,hang[i]-m);    for(int i=1;i<=m;i++)        add2(i+n,T,lie[i]-n);}int main(){    freopen("a.in","r",stdin);//  freopen("a.out","w",stdout);    int T; cin>>T; int cas=0;    while(T--){        if(cas) puts("");        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++){            scanf("%d",&tp[i]);            hang[i]=tp[i]-tp[i-1];        }        for(int i=1;i<=m;i++){            scanf("%d",&tp[i]);            lie[i]=tp[i]-tp[i-1];        }        build();        mxf();        printf("Matrix %d\n",++cas);        for(int i=1;i<=n;i++){            for(int j=1;j<=m;j++){                int x=((i-1)*m+(j-1))*2+2;                printf("%d ",e[x].flow+1);            }            puts("");        }    }}
原创粉丝点击