Uva 11082 Matrix Decompressing (最大流)

链接 : http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36866

可以建一个类似二分图,X集合是所有行,Y集合是所有列,X->Y的容量为(1到20)。建立源点连接每个X中的点,容量为该行的和。建立汇点连接Y中的点,容量为该行的列。目的是求从源点出发的流量就是容量,且必须走完所有流量并到达汇点,汇点的流量必须是源点发出的流量。这样控制路径后求出中间过程的流量各式多少。

因为题目规定了每行的和必须等于给定的数,所以从原点出发的必须是满流,到达汇点的流也是满流。由于直接计算会出现有些流量为0的情况不满足大于等于1小于等于20,所以可以一开始处理对整张图的点都减1 最后再加1。

/*--------------------- #headfile--------------------*/
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
/*----------------------#define----------------------*/
#define DRII(X,Y) int (X),(Y);scanf("%d%d",&(X),&(Y))
#define EXP 2.7182818284590452353602874713527
#define CASET int _;cin>>_;while(_--)
#define RII(X, Y) scanf("%d%d",&(X),&(Y))
#define DRI(X) int (X);scanf("%d", &X)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,n) for(int i=0;i<n;i++)
#define ALL(X) (X).begin(),(X).end()
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define RI(X) scanf("%d",&(X))
#define SZ(X) ((int)X.size())
#define PDI pair<double,int>
#define rson o<<1|1,m+1,r
#define PII pair<int,int>
#define MAX 0x3f3f3f3f
#define lson o<<1,l,m
#define MP make_pair
#define PB push_back
#define SE second
#define FI first
typedef long long ll;
template<class T>T MUL(T x,T y,T P){T F1=0;while(y){if(y&1){F1+=x;if(F1<0||F1>=P)F1-=P;}x<<=1;if(x<0||x>=P)x-=P;y>>=1;}return F1;}
template<class T>T POW(T x,T y,T P){T F1=1;x%=P;while(y){if(y&1)F1=MUL(F1,x,P);x=MUL(x,x,P);y>>=1;}return F1;}
template<class T>T gcd(T x,T y){if(y==0)return x;T z;while(z=x%y)x=y,y=z;return y;}
#define DRIII(X,Y,Z) int (X),(Y),(Z);scanf("%d%d%d",&(X),&(Y),&(Z))
#define RIII(X,Y,Z) scanf("%d%d%d",&(X),&(Y),&(Z))
const double pi = acos(-1.0);
const double eps = 1e-6;
const ll mod = 1000000007ll;
const int M = 100005;
const int N = 205;
using namespace std;

/*----------------------Main-------------------------*/

struct Edge {
    int to, c, rev;
    Edge() {}
    Edge(int _to, int _c, int _rev) {
        to = _to, c = _c, rev = _rev;
    }
};
vector<Edge> G[N];
int lv[N], iter[N];

void add(int from, int to, int c) {
    G[from].PB( Edge(to, c, SZ(G[to])) );
    G[to].PB( Edge(from, 0, SZ(G[from]) - 1) );
}

void BFS(int s) {
    mem(lv, -1);
    queue<int> q;
    lv[s] = 0;
    q.push(s);
    while(!q.empty()) {
        int v = q.front(); q.pop();
        for(int i = 0; i < SZ(G[v]); i++) {
            Edge &e = G[v][i];
            if(e.c > 0 && lv[e.to] < 0) {
                lv[e.to] = lv[v] + 1;
                q.push(e.to);
            }
        }
    }
}

int dfs(int v, int t, int f) {
    if(v == t) return f;
    for(int &i = iter[v]; i < SZ(G[v]); i++) {
        Edge &e = G[v][i];
        if(e.c > 0 && lv[v] < lv[e.to]) {
            int d = dfs(e.to, t, min(f, e.c));
            if(d > 0) {
                e.c -= d;
                G[e.to][e.rev].c += d;
                return d;
            }
        }
    }
    return 0;
}

int MF(int s, int t) {
    int res = 0;
    for(;;) {
        BFS(s);
        if(lv[t] < 0) return res;
        mem(iter, 0);
        int f;
        while((f = dfs(s, t, 1e9)) > 0) {
            res += f;
        }
    }
}

int n, m, FF = 0;
int A[N], B[N], a[N], b[N];

void solve() {

    if(FF) puts(""); FF++;
    RII(n, m);
    for(int i = 0; i <= n + m + 1; i++) G[i].clear();
    for(int i = 1; i <= n; i++) {
        RI(A[i]);
        a[i] = A[i] - A[i-1];
    }
    for(int i = 1; i <= m; i++) {
        RI(B[i]);
        b[i] = B[i] - B[i-1];
    }
    int s = 0, t = n + m + 1;

    for(int i = 1; i <= n; i++) {
        add(s, i, a[i] - m);
    }
    for(int i = 1; i <= m; i++) {
        add(i + n, t, b[i] - n);
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            add(i, j + n, 19);
        }
    }
    int ans = MF(0, n + m + 1) + n * m;
    assert(ans == A[n]);
    assert(ans == B[m]);
    printf("Matrix %d\n", FF);
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j < SZ(G[i]); j++) {
            Edge e = G[i][j];
            printf("%d%c", G[e.to][e.rev].c + 1, j == SZ(G[i]) - 1 ? '\n' : ' ');
        }
    }

}

int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    CASET
    solve();
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-19 20:39:06

Uva 11082 Matrix Decompressing (最大流)的相关文章

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 11082 - Matrix Decompressing(最大流)

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2023 题意: 对于一个R行C列的正整数矩阵(1≤R,C≤20),设Ai为前i行所有元素之和,Bi为前i列所有元素之和.已知R,C和数组A和B,找一个满足条件的矩阵.矩阵中的元素必须是1-20之间的正整数.输入保证有解. 分析: 首先根据Ai和Bi计算出第i行的元素之和Ai'和第i列

UVA 11082 Matrix Decompressing 矩阵解压(最大流,经典)

题意:知道矩阵的前i行之和,和前j列之和(任意i和j都可以).求这个矩阵.每个格子中的元素必须在1~20之间.矩阵大小上限20*20. 思路: 这么也想不到用网络流解决,这个模型很不错.假设这个矩阵的每一行是水管,每一列是水管,每行有出水口流到每一列,这样想比较好理解.然后每行的流量和每列的流量知道,就可以建图了. 建图过程,每行对应一个点,每列对应1个点,每行都可以流到每列,所以他们之间有边.我们得假设他们是如何流向的,不如设从行流向列,那么添加源点,流向每行:添加汇点,被每列汇流.容量怎么设

uva 11082 Matrix Decompressing 【 最大流 】

只看题目的话~~怎么也看不出来是网络流的题目的说啊~~~~ 建图好神奇~~ 最开始不懂---后来看了一下这篇-- http://www.cnblogs.com/AOQNRMGYXLMV/p/4280727.html 建立源点 st = 0,汇点 ed = r+c 因为正整数的范围是1到20,而流量可以是0,所以先将矩阵里面的每个数减去1,到最后输出答案的时候再加上1 把每一行看做一个节点 x,编号为1到r 把每一列看做一个节点y,编号为r+1到r+c st到x连边,容量为 Ai '- c y到e

[题解]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

UVa 11082 Matrix Decompressing (网络流)

链接:http://acm.hust.edu.cn/vjudge/problem/36866题意:对于一个R行C列的正整数矩阵(1≤R,C≤20),设Ai为前i行所有元素之和,Bi为前i列所有元素之和.已知R,C和数组A和B,找一个满足条件的矩阵.矩阵中的元素必须是1~20之间的正整数.输入保证有解.分析:这道题主要还是考查建模能力.如何把一个矩阵模型转化成网络流模型是关键之处.首先注意到矩阵任意行或列的元素之和是不变的(设第i行元素之和为Ai′,第i列元素之和为Bi′),因此想到把矩阵的每行和

UVA - 11082 Matrix Decompressing

很经典的网络流模型,行列分别看成一个点,行和列和分别看出容量,下界是1,所以先减去1,之后在加上就好了. 前向星建图的话,打印解会比较麻烦. #include<bits/stdc++.h> using namespace std; const int maxn = 42; struct Edge { int v,cap,flow; }; vector<Edge> edges; #define PB push_back vector<int> G[maxn]; void

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