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到ed连边,容量为Bi‘ - r

x到y连边,容量为19

这样再用一下 dinic

节点xi到yj的流量就是格子(i,j) - 1之后的值

这句话最开始非常非常的不理解-------

后来搜了下题解

因为yj的流量来自于各个x

同样的,xi的流量流向各个y,所以(i,j)这个格子的流量来源是xi

大概像这个图这样

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7
  8 const int maxn = 10005;
  9 const int INF = (1 << 30) - 1;
 10
 11 struct Edge{
 12     int v,next,c;
 13 }e[maxn];
 14
 15 int st,ed,lev[maxn],first[maxn],now[maxn],ecnt;
 16 int r,c;
 17
 18 void init(){
 19     memset(first,-1,sizeof(first));
 20     ecnt = 0;
 21 }
 22
 23 void addedges(int u,int v,int c){
 24     e[ecnt].next = first[u];
 25     e[ecnt].v = v;
 26     e[ecnt].c = c;
 27     first[u] = ecnt++;
 28
 29     e[ecnt].next = first[v];
 30     e[ecnt].v = u;
 31     e[ecnt].c = 0;
 32     first[v] = ecnt++;
 33 }
 34
 35 bool bfs(){
 36     queue<int> q;
 37     while(!q.empty()) q.pop();
 38     q.push(st);
 39     memset(lev,-1,sizeof(lev));
 40     lev[st] = 0;
 41     while(!q.empty()){
 42         int x = q.front();q.pop();
 43         for(int i = first[x];~i;i = e[i].next){
 44             int v = e[i].v;
 45             if(lev[v] < 0 && e[i].c > 0){
 46                 lev[v] = lev[x] + 1;
 47                 q.push(v);
 48             }
 49         }
 50     }
 51     return lev[ed] != -1;
 52 }
 53
 54 int dfs(int p,int minf){
 55     if(p == ed || minf == 0) return minf;
 56     for(int &i = now[p];~i;i = e[i].next){
 57         int v = e[i].v;
 58         if(lev[v] == lev[p] + 1 && e[i].c > 0){
 59             int d = dfs(v,min(e[i].c,minf));
 60             if(d > 0){
 61                 e[i].c -= d;
 62                 e[i^1].c += d;
 63                 return d;
 64             }
 65         }
 66     }
 67     return 0;
 68 }
 69
 70 int dinic(){
 71     int max_flow = 0,p1;
 72     while(bfs()){
 73         memcpy(now,first,sizeof(first));
 74         while((p1 = dfs(st,INF)) > 0)
 75         max_flow += p1;
 76     }
 77     return max_flow;
 78 }
 79
 80 int ans[55][55];
 81
 82 int main(){
 83     int T;
 84     scanf("%d",&T);
 85     int kase = 0;
 86     while(T--){
 87         scanf("%d %d",&r,&c);
 88         init();
 89         st = 0;ed = r+c+1;
 90
 91         int last = 0,cur;
 92         for(int i = 1;i <= r;i++){
 93             scanf("%d",&cur);
 94             addedges(st,i,cur-last-c);
 95             last = cur;
 96         }
 97
 98         last = 0;
 99         for(int i = 1;i <= c;i++){
100             scanf("%d",&cur);
101             addedges(i + r,ed,cur-last-r);
102             last = cur;
103         }
104
105         for(int i = 1;i <= r;i++)
106             for(int j = 1;j <= c;j++) addedges(i,j+r,19);
107
108         int res = dinic();
109
110         for(int u = 1;u <= r;u++){
111             for(int i = first[u];~i;i = e[i].next){
112                 int v = e[i].v;
113                 ans[u][v-r] = 19 - e[i].c;
114             }
115         }
116
117         printf("Matrix %d\n",++kase);
118         for(int i = 1;i <= r;i++){
119             printf("%d",ans[i][1] + 1);
120             for(int j = 2;j <= c;j++)
121             printf(" %d",ans[i][j] + 1);
122             printf("\n");
123         }
124         if(T) puts("");
125     }
126     return 0;
127 }

时间: 2024-11-05 13:59:26

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

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

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

题意:知道矩阵的前i行之和,和前j列之和(任意i和j都可以).求这个矩阵.每个格子中的元素必须在1~20之间.矩阵大小上限20*20. 思路: 这么也想不到用网络流解决,这个模型很不错.假设这个矩阵的每一行是水管,每一列是水管,每行有出水口流到每一列,这样想比较好理解.然后每行的流量和每列的流量知道,就可以建图了. 建图过程,每行对应一个点,每列对应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

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