题意:

  给出一个矩阵前i行的和与前j列的和,(i∈[1,r],j属于[1,c]),每个元素ai,j∈[1,20],请你还原出这个矩阵,保证有解.

SOL:

  给网络流建模跪了,神一样的建图,如果我我会怎么做呢?...搜索?然而每个元素具有行,列双重相关性...暴力都打不出来吧...

  然而我们顺着搜索的方向想,如果每个点的搜索值最终小于这行的和,那么我们应该做什么?增大它!是不是感觉有点增广的想法出来了------>然而我只是瞎BB...事后觉得可以这么想但考场上并不能这么想出来...

  考虑它的建图,因为每个元素至少为1,即流量至少为1,那它就变成一个有上下界的网络流问题...不会怎么办?因为每个元素都大于等于1那么我们把他都减一!

  我们对每一行的和对应一个点与超级源S相连,容量为这一行的和,对于每条列我们建一个点与汇点相连,容量为列的和,然后行与列的点两两相连,容量为19,也就是数的最大值,然后跑一遍最大流,行与列之间每条边的流量就是原矩阵中的元素.

  如何证明它的正确性?

  显然所有行与列的和是相等的,即源汇的出入边一定都满流,同时,我们可以把每一行与所有列的连边上的流量看做该行对此列所做的"贡献",因为最大流一定使源汇出入边满流,所以一定有一种方案.那么这个显然是正确的.

  发现行与列的关系以及和的限制条件,也许是思路突破的关键吧.

  

  警报!警报!警报!!

    自己打的代码莫名TLE了...因为点不多所以老人家写的EK,然而我写的dinic居然TLE了?smg?...因为时间不多先贴上代码,以后有空回来看...模型是关健啊.

 TLE代码:

  

  1. /*==========================================================================
  2. # Last modified: 2016-03-08 08:03
  3. # Filename: uva11082.cpp
  4. # Description:
  5. ==========================================================================*/
  6. #define me AcrossTheSky
  7. #include <cstdio>
  8. #include <cmath>
  9. #include <ctime>
  10. #include <string>
  11. #include <cstring>
  12. #include <cstdlib>
  13. #include <iostream>
  14. #include <algorithm>
  15.  
  16. #include <set>
  17. #include <map>
  18. #include <stack>
  19. #include <queue>
  20. #include <vector>
  21.  
  22. #define lowbit(x) (x)&(-x)
  23. #define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
  24. #define FORP(i,a,b) for(int i=(a);i<=(b);i++)
  25. #define FORM(i,a,b) for(int i=(a);i>=(b);i--)
  26. #define ls(a,b) (((a)+(b)) << 1)
  27. #define rs(a,b) (((a)+(b)) >> 1)
  28. #define getlc(a) ch[(a)][0]
  29. #define getrc(a) ch[(a)][1]
  30.  
  31. #define maxn 1000
  32. #define maxm 1000000
  33. #define pi 3.1415926535898
  34. #define _e 2.718281828459
  35. #define INF 1070000000
  36. using namespace std;
  37. typedef long long ll;
  38. typedef unsigned long long ull;
  39.  
  40. template<class T> inline
  41. void read(T& num) {
  42. bool start=false,neg=false;
  43. char c;
  44. num=0;
  45. while((c=getchar())!=EOF) {
  46. if(c=='-') start=neg=true;
  47. else if(c>='0' && c<='9') {
  48. start=true;
  49. num=num*10+c-'0';
  50. } else if(start) break;
  51. }
  52. if(neg) num=-num;
  53. }
  54. /*==================split line==================*/
  55. struct Edge{
  56. int from,to,cap,v;
  57. }e[maxm];
  58. int r,c;
  59. int id[maxn][maxn],a[maxn],b[maxn];
  60. int first[maxn],next[maxm],cur[maxn],d[maxn];
  61. bool vis[maxn];
  62. int sume=1,n,S,T;
  63. void addedge(int x,int y,int cap){
  64. sume++; e[sume].from=x; e[sume].to=y; e[sume].cap=cap;
  65. next[sume]=first[x]; first[x]=sume; id[x][y]=sume;
  66. sume++; e[sume].from=y; e[sume].to=x; e[sume].cap=0;
  67. next[sume]=first[y]; first[y]=sume; id[y][x]=sume;
  68. }
  69. void reset(){
  70. sume=1;
  71. a[0]=b[0]=0;
  72. memset(e,0,sizeof(e));
  73. memset(next,0,sizeof(next));
  74. memset(first,0,sizeof(first));
  75. memset(a,0,sizeof(a));
  76. memset(b,0,sizeof(b));
  77. //T=maxn-10,S=0;
  78. }
  79. bool bfs(){
  80. queue<int>q;
  81. FORP(i,S,T) d[i]=INF;
  82. //memset(vis,false,sizeof(vis));
  83. q.push(S); d[S]=0; //vis[S]=true;
  84. while (!q.empty()){
  85. int now=q.front(); q.pop();
  86. for (int i=first[now];i;i=next[i])
  87. if (d[e[i].to]==INF && e[i].cap){
  88. d[e[i].to]=d[now]+1;
  89. //vis[e[i].to]=true;
  90. q.push(e[i].to);
  91. }
  92. }
  93. return d[T]<INF;
  94. }
  95. int dfs(int now,int a){
  96. if (now==T || !a) return a;
  97. int f,flow=0;
  98. for (int &i=cur[now];i;i=next[i])
  99. if (d[now]+1==d[e[i].to] && (f=dfs(e[i].to,min(a,e[i].cap)))>0){
  100. flow+=f; a-=f; e[i].cap-=f; e[i].v+=f; e[i^1].cap+=f;
  101. if (!a) break;
  102. }
  103. return flow;
  104. }
  105. void dinic(){
  106. int flow=0;
  107. while (bfs()){
  108. FORP(i,0,n) cur[i]=first[i];
  109. flow+=dfs(S,INF);
  110. }
  111. }
  112. int main(){
  113. int cas; read(cas); //int cass=1;
  114. FORP(cass,1,cas){
  115. reset();
  116. scanf("%d%d",&r,&c);
  117. n=r+c+1; S=0; T=r+c+4;
  118. FORP(i,1,r) scanf("%d",&a[i]);//read(a[i]);
  119. FORP(i,1,c) scanf("%d",&b[i]);//read(b[i]);
  120. FORP(i,1,r) addedge(0,i,a[i]-a[i-1]-c);
  121. FORP(i,1,r)
  122. FORP(j,r+1,r+c+1) addedge(i,j,19);
  123. FORP(j,r+1,r+c+1) addedge(j,T,b[j-r]-b[j-r-1]-r);
  124. printf("Matrix %d\n",cass); //cass++;
  125. dinic();
  126. FORP(i,1,r)
  127. FORP(j,1,c)
  128. printf("%d%c",e[id[i][j+r]].v+1,(j==c)?'\n':' ');
  129. if (cas) cout << endl;
  130. }
  131. }

lrj代码:

  

  1. // UVa11082 Matrix Decompressing
  2. // Rujia Liu
  3. // Slower version with EdmondsKarp
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<queue>
  7. #include<vector>
  8. #include<algorithm>
  9. using namespace std;
  10.  
  11. const int maxn = 50 + 5;
  12. const int INF = 1000000000;
  13.  
  14. struct Edge {
  15. int from, to, cap, flow;
  16. Edge(int u, int v, int c, int f):from(u),to(v),cap(c),flow(f) {}
  17. };
  18.  
  19. struct EdmondsKarp {
  20. int n, m;
  21. vector<Edge> edges; // 边数的两倍
  22. vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
  23. int a[maxn]; // 当起点到i的可改进量
  24. int p[maxn]; // 最短路树上p的入弧编号
  25.  
  26. void init(int n) {
  27. for(int i = 0; i < n; i++) G[i].clear();
  28. edges.clear();
  29. }
  30.  
  31. void AddEdge(int from, int to, int cap) {
  32. edges.push_back(Edge(from, to, cap, 0));
  33. edges.push_back(Edge(to, from, 0, 0));
  34. m = edges.size();
  35. G[from].push_back(m-2);
  36. G[to].push_back(m-1);
  37. }
  38.  
  39. int Maxflow(int s, int t) {
  40. int flow = 0;
  41. for(;;) {
  42. memset(a, 0, sizeof(a));
  43. queue<int> Q;
  44. Q.push(s);
  45. a[s] = INF;
  46. while(!Q.empty()) {
  47. int x = Q.front(); Q.pop();
  48. for(int i = 0; i < G[x].size(); i++) {
  49. Edge& e = edges[G[x][i]];
  50. if(!a[e.to] && e.cap > e.flow) {
  51. p[e.to] = G[x][i];
  52. a[e.to] = min(a[x], e.cap-e.flow);
  53. Q.push(e.to);
  54. }
  55. }
  56. if(a[t]) break;
  57. }
  58. if(!a[t]) break;
  59. for(int u = t; u != s; u = edges[p[u]].from) {
  60. edges[p[u]].flow += a[t];
  61. edges[p[u]^1].flow -= a[t];
  62. }
  63. flow += a[t];
  64. }
  65. return flow;
  66. }
  67. };
  68.  
  69. EdmondsKarp g;
  70. int no[maxn][maxn];
  71.  
  72. int main() {
  73. int T, R, C, v, kase = 0;
  74. scanf("%d", &T);
  75. for(int kase = 1; kase <= T; kase++) {
  76. scanf("%d%d", &R, &C);
  77. g.init(R+C+2);
  78. int last = 0;
  79. for(int i = 1; i <= R; i++) {
  80. scanf("%d", &v);
  81. g.AddEdge(0, i, v - last - C); // row sum is v - last
  82. last = v;
  83. }
  84. last = 0;
  85. for(int i = 1; i <= C; i++) {
  86. scanf("%d", &v);
  87. g.AddEdge(R+i, R+C+1, v - last - R); // col sum is v - last
  88. last = v;
  89. }
  90. for(int i = 1; i <= R; i++)
  91. for(int j = 1; j <= C; j++) {
  92. g.AddEdge(i, R+j, 19);
  93. no[i][j] = g.edges.size() - 2; // no[i][j] is the index of arc for cell(i,j)
  94. }
  95. g.Maxflow(0, R+C+1);
  96.  
  97. printf("Matrix %d\n", kase);
  98. for(int i = 1; i <= R; i++) {
  99. for(int j = 1; j <= C; j++)
  100. printf("%d ", g.edges[no[i][j]].flow + 1); // we subtracted 1 from every cell
  101. printf("\n");
  102. }
  103. printf("\n");
  104. }
  105. return 0;
  106. }

UVa 11082 & 最大流的行列模型的更多相关文章

  1. UVA - 11082 Matrix Decompressing(最大流+行列模型)

    题目大意:给出一个R行C列的矩阵,如今给出他的前1-R行和 && 前1-C列和,问这个矩阵原来是如何的,要求每一个元素大小在1-20之间 解题思路:将每一行连接到超级源点,容量为该行的 ...

  2. 【网络流#5】UVA 11082 最大流

    网络流题目最有意思的地方就是构图了,毕竟套模板每个人都会的 现在有一个矩阵,已知前i行元素之和a[i](1<=i<=n),前j列元素之和b[j](1<=j<=m),求一个可行的 ...

  3. uva Matrix Decompressing (行列模型)

    Matrix Decompressing 题目:    给出一个矩阵的前i行,前j列的和.要求你求出满足的矩阵. 矩阵的数范围在[1,20].   一開始就坑在了这里.没读细致题目. 囧...   事 ...

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

    题意: 知道矩阵的前i行之和,和前j列之和(任意i和j都可以).求这个矩阵.每个格子中的元素必须在1~20之间.矩阵大小上限20*20. 思路: 这么也想不到用网络流解决,这个模型很不错.假设这个矩阵 ...

  5. UVa 11082 - Matrix Decompressing(最大流)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  6. 紫书 例题11-8 UVa 11082(网络流最大流)

    这道题的建模真的非常的秀, 非常牛逼. 先讲建模过程.源点到每一行连一条弧, 容量为这一行的和减去列数, 然后每一列到汇点连一条弧, 容量为这一列 的和减去行数, 然后每一行和列之间连一条弧, 容量为 ...

  7. UVA - 11082 Matrix Decompressing (最大流,技巧)

    很经典的网络流模型,行编号和列编号分别看成一个点,行和列和分别看出容量,一个点(x,y)看出是一条边,边的容量下界是1,所以先减去1,之后在加上就好了. 建图的时候注意分配好编号,解从残留网络中的边找 ...

  8. [网络流最大流经典][uva 11082][矩阵解压]

    题目大意 分析 #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring ...

  9. UVa 11082 Matrix Decompressing(最大流)

    不想吐槽了..sample input 和sample output 完全对不上...调了一个晚上...不想说什么了... -------------------------------------- ...

随机推荐

  1. Hadoop CDH5 集群管理

    Hadoop 是一个开源项目,所以很多公司在这个基础进行商业化,Cloudera 对 Hadoop做了相应的改变.Cloudera 公司的发行版,我们将该版本称为 CDH(Cloudera Distr ...

  2. java 中的一个项目如何做到访问另一个项目的一个方法 或者 页面

    两种方法:1.将一个项目打成jar包,第二个项目进行导入该jar包,就可以使用第一个项目里的类方法属性等2.将第一个项目发布出去,然后第二个项目调用,所谓发布出去就是开发远程接口,允许其他人调用.

  3. OpenCv,EmguCv及.net之间的互动(The Interaction of OpenCv, EmguCv AND .net)

    http://www.cnblogs.com/xrwang/archive/2010/01/26/TheInteractionOfOpenCv-EmguCvANDDotNet.html 前言 在.ne ...

  4. Jmeter 提取http请求返回值里json数据参数化方法

    第三方插件下载地址:http://jmeter-plugins.org/downloads/all/ 插件下载后解压:找到JMeterPlugins-Extras.jar,把JMeterPlugins ...

  5. PortSentry是入侵检测工具中配置最简单、效果最直接的工具之一

    https://sourceforge.net/projects/sentrytools/ [root@localhost ~]# tar -xzvf portsentry-1.2.tar.gz [r ...

  6. WebService – 2.动态调用WebService

    在本节课程中,将演示如何通过程序动态添加.调用.编译.执行WebService并返回结果. WebService动态调用示意图 WebService相关知识 代码文档对象模型CodeDom的使用 编程 ...

  7. Java代码实现excel数据导入到Oracle

    1.首先需要两个jar包jxl.jar,ojdbc.jar(注意版本,版本不合适会报版本错误)2.代码: Java代码   import java.io.File; import java.io.Fi ...

  8. 限定符【const】用法大全

    1. 限定符声明变量只能被读 const int i=5; int j=0; ... i=j; //非法,导致编译错误 j=i; //合法 2. 必须初始化 const int i=5; //合法 c ...

  9. leetcode4568

    date: 2015-09-13 16:32:49 Median of Two Sorted Arrays There are two sorted arrays nums1 and nums2 of ...

  10. 两个本地(localhost)html文件之间的传值

    什么是iframe? iframe 元素会创建包含另外一个文档的内联框架(即行内框架).可以理解为把iframe解释成“浏览器中的浏览器“ 在IE中: document.frames[i].docum ...