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′),因此想到把矩阵的每行和每列都看成是一个结点,然后增设一个源点s和一个汇点t,并将矩阵中的每个元素减1,
然后从源点s向各个行结点Xi连一条弧,那么容量为Ai′-C(由于先前使每个元素减去1每行总的减去C,使得s到Xi的容量下界为0上界为Ai′-C),从各个列结点Yi向t连一条弧,容量为Bi′-R(同理),对于每个矩阵元素(Xi,Yj),从结点Xi向Yj连一条弧,容量为19,接下来就是求s-t的最大流,有解的条件是s出发和到达t都要满载,原因是每行和每列的元素之和是不变的,格子(i,j)的值就是结点Xi->Yj的流量加上1(先前每个元素都减去了1)。
  1 #include <cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<vector>
  5 #include<algorithm>
  6 using namespace std;
  7
  8 const int maxn = 40 + 5;
  9 const int INF = 1000000000;
 10
 11 struct Edge {
 12     int from, to, cap, flow;
 13     Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
 14 };
 15
 16 struct EdmondsKarp {
 17     int n, m;
 18     vector<Edge> edges;
 19     vector<int> G[maxn];
 20     int a[maxn];
 21     int p[maxn];
 22
 23     void init(int n) {
 24         for (int i = 0; i < n; i++) G[i].clear();
 25         edges.clear();
 26     }
 27
 28     void AddEdge(int from, int to, int cap) {
 29         edges.push_back(Edge(from, to, cap, 0));
 30         edges.push_back(Edge(to, from, 0, 0));
 31         m = edges.size();
 32         G[from].push_back(m - 2);
 33         G[to].push_back(m - 1);
 34     }
 35
 36     int Maxflow(int s, int t) {
 37         int flow = 0;
 38         for (;;) {
 39             memset(a, 0, sizeof(a));
 40             queue<int> Q;
 41             Q.push(s);
 42             a[s] = INF;
 43             while (!Q.empty()) {
 44                 int x = Q.front(); Q.pop();
 45                 for (int i = 0; i < G[x].size(); i++) {
 46                     Edge& e = edges[G[x][i]];
 47                     if (!a[e.to] && e.cap > e.flow) {
 48                         p[e.to] = G[x][i];
 49                         a[e.to] = min(a[x], e.cap - e.flow);
 50                         Q.push(e.to);
 51                     }
 52                 }
 53                 if (a[t]) break;
 54             }
 55             if (!a[t]) break;
 56             for (int u = t; u != s; u = edges[p[u]].from) {
 57                 edges[p[u]].flow += a[t];
 58                 edges[p[u] ^ 1].flow -= a[t];
 59             }
 60             flow += a[t];
 61         }
 62         return flow;
 63     }
 64 };
 65
 66 EdmondsKarp g;
 67 int idex[maxn][maxn];
 68
 69 int main() {
 70     int T;
 71     scanf("%d", &T);
 72     for (int kase = 1; kase <= T; kase++) {
 73         int r, c;
 74         scanf("%d%d", &r, &c);
 75         g.init(r + c + 2);
 76         int v, last = 0;
 77         for (int i = 1; i <= r; i++) {
 78             scanf("%d", &v);
 79             g.AddEdge(0, i, v - last - c);
 80             last = v;
 81         }
 82         last = 0;
 83         for (int i = 1; i <= c; i++) {
 84             scanf("%d", &v);
 85             g.AddEdge(r + i, r + c + 1, v - last - r);
 86             last = v;
 87         }
 88         for (int i = 1; i <= r; i++)
 89             for (int j = 1; j <= c; j++) {
 90                 g.AddEdge(i, r + j, 19);
 91                 idex[i][j] = g.edges.size() - 2;
 92             }
 93         g.Maxflow(0, r + c + 1);
 94         printf("Matrix %d\n", kase);
 95         for (int i = 1; i <= r; i++) {
 96             for (int j = 1; j <= c; j++)
 97                 printf("%d ", g.edges[idex[i][j]].flow + 1);
 98             putchar(‘\n‘);
 99         }
100         putchar(‘\n‘);
101     }
102     return 0;
103 }
				
时间: 2024-10-12 07:54:46

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

开始眨眼一看怎么也不像是网络流的一道题,再怎么看也觉得像是搜索.不过虽然这道题数据范围很小,但也不至于搜索也是可以随随便便就可以过的.(不过这道题应该是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中的点连线,他们之间也有一定的容量制约关系(具体看题目中的边权值限制).这样就可以求出最大流量匹配了. 有时我们要求完美匹配,即所有流入的量等于流出的量  . 该题构思极其巧妙,因为我