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

  

时间: 2024-10-26 01:53:06

UVA-11082 Matrix Decompressing (网络流建模)的相关文章

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

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

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

开始眨眼一看怎么也不像是网络流的一道题,再怎么看也觉得像是搜索.不过虽然这道题数据范围很小,但也不至于搜索也是可以随随便便就可以过的.(不过这道题应该是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

很经典的网络流模型,行列分别看成一个点,行和列和分别看出容量,下界是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

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 矩阵解压(最大流,经典)

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

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

链接 : http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36866 可以建一个类似二分图,X集合是所有行,Y集合是所有列,X->Y的容量为(1到20).建立源点连接每个X中的点,容量为该行的和.建立汇点连接Y中的点,容量为该行的列.目的是求从源点出发的流量就是容量,且必须走完所有流量并到达汇点,汇点的流量必须是源点发出的流量.这样控制路径后求出中间过程的流量各式多少. 因为题目规定了每行的和必须等于给定的数,所以从原点出发

11082 - Matrix Decompressing (网络流建模|二分图匹配)

该题是一道经典的二分图匹配的题目 .现在终于有点明白什么是二分图匹配了,其实说白了就是依赖于最大流算法之上的一种解决特定问题的算法 . 所谓二分图,就是我们假定有两个集合A和B,每个集合中有若干元素(点),其中源点与A相连,汇点与B相连,并且他们的总容量决定了最终答案的上限,所以一定要维护好 . 然后由A中的点向B中的点连线,他们之间也有一定的容量制约关系(具体看题目中的边权值限制).这样就可以求出最大流量匹配了. 有时我们要求完美匹配,即所有流入的量等于流出的量  . 该题构思极其巧妙,因为我