uva11082 Matrix Decompressing

网络流

首先算出每行每列的数的和。

每行的值减去c,每列的值减去R

然后每行和每列之间连边,容量为19.

这样一来,(i,j)的流量相当于(i,j)的值-1.

这样就避免了流量为0不对应答案的尴尬情况。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1000 + 10;
const int maxm = 100000 + 10;
const int inf = 0x3f3f3f3f;

int g[maxn],v[maxm],nex[maxm],f[maxm],eid;
int gap[maxn],d[maxn],vid;
int n,m,S,T;
int a[maxn],b[maxn];
int res[maxn][maxn];

void addedge(int a,int b,int F) {
    v[eid]=b; f[eid]=F; nex[eid]=g[a]; g[a]=eid++;
    v[eid]=a; f[eid]=0; nex[eid]=g[b]; g[b]=eid++;
}

void build() {
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=n;i>=1;i--) a[i]-=a[i-1];
    for(int i=n+1;i<=n+m;i++) scanf("%d",&b[i]);
    for(int i=n+m;i>=n+1;i--) b[i]-=b[i-1];
    memset(g,-1,sizeof(g)); eid=0;
    S=n+m+1; T=n+m+2; vid=n+m+2;
    for(int i=1;i<=n;i++) {
        addedge(S,i,a[i]-m);
    }
    for(int i=n+1;i<=n+m;i++) {
        addedge(i,T,b[i]-n);
    }
    for(int i=1;i<=n;i++)
    for(int j=n+1;j<=n+m;j++) {
        addedge(i,j,19);
    }
}

int ISAP(int u,int flow) {
    if(u==T) return flow;
    int cur=0,aug,mindist=vid;

    for(int i=g[u];~i;i=nex[i]) if(f[i] && d[u]==d[v[i]]+1) {
        aug=ISAP(v[i],min(flow-cur,f[i]));
        cur+=aug;
        f[i]-=aug;
        f[i^1]+=aug;
        if(cur==flow || d[S]>=vid) return cur;
    }

    if(cur==0) {
        if(!--gap[d[u]]) {
            d[S]=vid;
            return cur;
        }
        for(int i=g[u];~i;i=nex[i]) if(f[i])
            mindist=min(mindist,d[v[i]]);
        ++gap[d[u]=mindist+1];
    }
    return cur;
}

void solve() {
    memset(d,0,sizeof(d));
    memset(gap,0,sizeof(gap));
    gap[0]=vid;
    while(d[S]<vid) {

        ISAP(S,inf);
    }
    for(int u=1;u<=n;u++) {
        for(int i=g[u];~i;i=nex[i]) res[u][v[i]]=20-f[i];
    }
    for(int i=1;i<=n;i++) {
        for(int j=n+1;j<n+m;j++)
            printf("%d ",res[i][j]);
        printf("%d\n",res[i][n+m]);
    }
}

int main() {
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;i++) {
        if(i>1) printf("\n");
        printf("Matrix %d\n",i);
        build();
        solve();
    }
    return 0;
}
时间: 2024-12-25 02:33:16

uva11082 Matrix Decompressing的相关文章

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列的和,获得每一行的和以及每一列的和. 把每一行看做一个节点,每一列看做一个节点. 建立一个源点到达每一行. 建立一个汇点,

UVA-11082 Matrix Decompressing(有上下界的最大流)

题目链接: Matrix Decompressing 题意: 给一个矩阵的每行和每列的和,(给的是前i行或者列的和); 矩阵中每个元素的值在1到20之间,找出这样的一个矩阵: 思路: 把它转化成一个二分图,每行和每列之间连一条弧,然后设置一个源点和一个汇点,源点与行点相连,汇点与列点相连,求一个最大值,当然这是一个有下界的最大流,需要做-1的处理,同时与源汇相连的边也是要处理的;最后求得的反向边+1就是答案了; AC代码: #include <bits/stdc++.h> /*#include

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

题目大意:给出一个由1到20组成的整数矩阵的每一行和每一列的和,构造这个矩阵.输出任意一个构造方案. 题目分析:将每一行视作一个点x,将每一列视作一个点y.对于矩阵中的每一个格子,都对应一个二元关系<x,y>,从x连一条有向弧到y,容量置为19.增加源点s和汇点t,对于每一个x,连一条从s到x的有向弧,容量置为对应的该行总和减去列数,对于每一个y,连一条从y到t的有向弧,容量置为对应的该列总和减去行数.对于这个寻找最大流,算法终止后,如果从s出发的每一条弧和到达t的每一条弧都是饱和的,那么每一

UVa11082 Matrix Decompressing(最小费用最大流)

题目大概有一个n*m的矩阵,已知各行所有数的和的前缀和和各列所有数的和的前缀和,且矩阵各个数都在1到20的范围内,求该矩阵的一个可能的情况. POJ2396的弱化版本吧..建图的关键在于: 把行.列看成点,各单元看成边 这个建图感觉非常巧.. 各个单元有下界限制..这个我可不想再写带下界的最大流.. 想了下,发现可以用最小费用最大流求解:通过放大边的费用,使得这条边成为一条必须会被经过的边. 简单来说就是各单元代表的边拆成两条,一条容量1费用-1,另外一条容量19费用0.这样跑MCMF,显然为了

UVa 11082 Matrix Decompressing(最大流)

不想吐槽了..sample input 和sample output 完全对不上...调了一个晚上...不想说什么了... ------------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vect

UVA 11082 - Matrix Decompressing(网络流+行列模型)

UVA 11082 - Matrix Decompressing 题目链接 题意:给定一个矩阵每行每列的和,要求现在构造一个矩阵满足元素在1-20之间,行列和满足条件 思路:行列建图,源点连到每个行,容量为和,每列连到汇点,容量为和,每行连到每列,容量20,注意这题要求的是1-20,所以可以先把所有位置-1,最后输出的时候+1即可 代码: #include <cstdio> #include <cstring> #include <queue> #include <

uva Matrix Decompressing (行列模型)

Matrix Decompressing 题目:    给出一个矩阵的前i行,前j列的和.要求你求出满足的矩阵.矩阵的数范围在[1,20].   一开始就坑在了这里.没读仔细题目.囧...   其实这题的模型就是一个网络流的行列模型,跟poj的那题budge一样建图.不过Poj 的那个建图输入麻烦,而这题是裸的,因为已经告诉你了下界为1,上界为20,囧...而且poj那题我至今也不知道为什么我会一直超时.T_T 算法:    行列模型可以转换成网络流的有源汇上下界网络流求解.而行号和列号分别作为

【UVA11082】Matrix Decompressing(有上下界的网络流)

题意:给出一个矩阵前i列所有元素的和,和前j行所有元素的和,求这个矩阵解压以后的原型.(答案不唯一) n,m<=20,1<=a[i,j]<=20 思路:这道题把边上的流量作为原先矩阵中的点 把每一行,每一列都看成一个点 S-->i行 a[i]-m i行-->j列 19 j列-->T b[i]-n 跑最大流,边(i,j+n)上的流量就是a[i,j]的值 为什么容量是a[i]-m,19,b[i]-n? 因为点权(边权)不能为0,所以要先把所有值+1,上限就-1,输出的时候+

[题解]UVa 11082 Matrix Decompressing

开始眨眼一看怎么也不像是网络流的一道题,再怎么看也觉得像是搜索.不过虽然这道题数据范围很小,但也不至于搜索也是可以随随便便就可以过的.(不过这道题应该是special judge,因为一题可以多解而且题目中然而并没有什么要求,所以说可以考虑思考一下这道题有木有什么"套路"之类的通法) 比如说有这么一组数据 原矩阵 1 2 3 4 7 8 9 5 6 输入 3 3 6 25 45 14 28 45 然后将每一行的和写在每一列对应的行上(很明显有问题) 6 0 0 19 0 0 20 0