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

题意:知道矩阵的前i行之和,和前j列之和(任意i和j都可以)。求这个矩阵。每个格子中的元素必须在1~20之间。矩阵大小上限20*20。

思路:

  这么也想不到用网络流解决,这个模型很不错。假设这个矩阵的每一行是水管,每一列是水管,每行有出水口流到每一列,这样想比较好理解。然后每行的流量和每列的流量知道,就可以建图了。

  建图过程,每行对应一个点,每列对应1个点,每行都可以流到每列,所以他们之间有边。我们得假设他们是如何流向的,不如设从行流向列,那么添加源点,流向每行;添加汇点,被每列汇流。容量怎么设?我们要让每行都满流就行了,那么行之和就是源点到该行的容量,同理汇点也如此。但是每行流向每列呢?注意每个格子的元素必须在1~20之间,所以把容量设为20,别让它流太多了。

  注意到元素必须在1~20之间!!!那么这样增广路的话会出现有的完全0流怎么办?先将每个格子中的元素自减1,它的流下限总不会为负吧,计算完输出时再加回去不就行了。

  1 #include <bits/stdc++.h>
  2 #define LL long long
  3 #define pii pair<int,int>
  4 #define INF 0x7f7f7f7f
  5 using namespace std;
  6 const int N=10000+100;
  7
  8 struct node
  9 {
 10     int from;
 11     int to;
 12     int cap;
 13     int flow;
 14 }edge[N];
 15
 16 int row[30];
 17 int col[30];
 18 int edge_cnt;
 19 vector<int> vect[1000];
 20
 21 void add_node(int from,int to,int cap,int flow)
 22 {
 23     edge[edge_cnt].from=from;
 24     edge[edge_cnt].to=to;
 25     edge[edge_cnt].cap=cap;
 26     edge[edge_cnt].flow=flow;
 27     vect[from].push_back(edge_cnt);
 28     edge_cnt++;
 29 }
 30
 31 void build_graph(int n,int m)
 32 {
 33     for(int i=1; i<=n; i++) //加源点
 34     {
 35         add_node(0, i, row[i], 0);
 36         add_node(i ,0, 0, 0);
 37     }
 38
 39     for(int i=1; i<=m; i++) //汇点
 40     {
 41         add_node(n+i, n+m+1, col[i], 0);
 42         add_node(n+m+1, n+i, 0, 0);
 43     }
 44
 45     for(int i=1; i<=n; i++) //行-列
 46     {
 47         for(int j=1; j<=m; j++)
 48         {
 49             add_node(i,n+j,19,0);
 50             add_node(n+j, i,0,0);
 51         }
 52     }
 53 }
 54
 55 int flow[1000];
 56 int path[1000];
 57 int matrix[50][50];
 58
 59 int BFS(int s,int e)
 60 {
 61     deque<int> que;
 62     que.push_back(s);
 63     flow[s]=INF;
 64
 65     while(!que.empty())
 66     {
 67         int x=que.front();
 68         que.pop_front();
 69         for(int i=0; i<vect[x].size(); i++)
 70         {
 71             node e=edge[vect[x][i]];
 72             if(!flow[e.to] && e.cap>e.flow)
 73             {
 74                 path[e.to]=vect[x][i];
 75                 flow[e.to]=min(flow[e.from],e.cap-e.flow);
 76                 que.push_back(e.to);
 77             }
 78         }
 79         if(flow[e]) return flow[e];
 80     }
 81     return flow[e];
 82 }
 83
 84 int cal(int s, int e)
 85 {
 86     int ans=0;
 87     while(true)
 88     {
 89         memset(flow,0,sizeof(flow));
 90         memset(path,0,sizeof(path));
 91
 92         int tmp=BFS(s,e);
 93         if(tmp==0)  return ans;
 94
 95         ans+=tmp;
 96         int ed=e;
 97         while(ed!=s)
 98         {
 99             int t=path[ed];
100             edge[t].flow+=tmp;
101             edge[t^1].flow-=tmp;
102             ed=edge[t].from;
103         }
104
105     }
106     return 0;
107 }
108
109 void get_ans(int n,int m)
110 {
111     for(int i=0; i<edge_cnt; i+=2)
112     {
113         node e=edge[i];
114         if(e.to<n)  continue;
115         matrix[e.from][e.to-n]=e.flow;
116     }
117     for(int i=1; i<=n; i++)
118     {
119         for(int j=1; j<=m; j++)
120             printf("%d ", matrix[i][j]+1);
121         printf("\n");
122     }
123 }
124
125
126 int main()
127 {
128     //freopen("input.txt", "r", stdin);
129     int r, c, t, k, Case=0;
130     cin>>t;
131     while(t--)
132     {
133         for(int i=0; i<1000; i++)    vect[i].clear();
134         memset(matrix,0,sizeof(matrix));
135         memset(row,0,sizeof(row));
136         memset(col,0,sizeof(col));
137         memset(edge,0,sizeof(edge));
138         edge_cnt=0;
139
140
141         scanf("%d%d",&r,&c);
142         for(int i=1; i<=r; i++)  //行
143             scanf("%d",&row[i]);
144
145         for(int i=1; i<=c; i++)  //列
146             scanf("%d",&col[i]);
147
148         for(int i=r; i>0; i--)  //换成每行-c
149             row[i]-=row[i-1]+c;//细心点
150         for(int i=c; i>0; i--)  //换成每列-r
151             col[i]-=col[i-1]+r;
152
153         printf("Matrix %d\n",++Case);
154         build_graph(r, c);
155         cal(0, r+c+1);
156         get_ans(r,c);
157         if(t)   cout<<endl;
158     }
159     return 0;
160 }

AC代码

时间: 2024-12-16 11:30:49

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

链接: 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中的点,容量为该行的列.目的是求从源点出发的流量就是容量,且必须走完所有流量并到达汇点,汇点的流量必须是源点发出的流量.这样控制路径后求出中间过程的流量各式多少. 因为题目规定了每行的和必须等于给定的数,所以从原点出发

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

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

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