UVA - 11082 Matrix Decompressing
2. B - Matrix Decompressing
题意:定义一个R*C的正整数矩阵(1<=R,C<=20),设Ai为前i行所有元素之和,Bi为前i列所有元素之和。
题目已知R,C和数组A,B。要找一个满足条件的矩阵。矩阵中的元素要满足(1<=X[i][j]<=20)。
思路:

根据a,b数组求出每一行的元素之和a,每一列的元素之和b 建一个源点s=0,汇点t=R+C+1
然后每一行看成一个顶点1~R,每一列看成一个顶点R+1~R+C
矩阵中每一个位置看成是一条边,比如2行3列的点,就是连接第2行和第3列的点的边。 然后从s到每一行建一条边,容量为a[i],
从每一列到t建一条边,容量为b[i] 然后每一行的点向每一列的点建边,容量为20(暂且说是20,继续看下去,20是错的,19才是对的)
这样的图的意义: 整个矩阵的和代表总的流量 从s出发,分别流向R行(所以有a1+…+a[R]=总流量)
每一行的流量会分给该行的C个元素,每一个列的顶点会从R行获得总的流量,就是该列的流量,最后流到t的总流量还是s出发的流量。
所以行的顶点和列的顶点的R*C条边流过的流量就代表矩阵中R*C个位置的值。
因为题目要求矩阵的位置的值在1~20之间,
所以R*C条边的流量应该在1~20之间,所以R*C条边的最大流量即容量就是20.
但是这样是有问题的,我们好像忽略了一个问题,如果某一条边没有流量怎么办?
某一条边流量为0的情况下,就不能满足矩阵中的元素在1~20之间了
可以先给所有的边给一个值为1的流量,这样的话条件就改成了1~19 了。
求到的最后流量值+1就是矩阵中的元素值。
解决代码:
#include<bits/stdc++.h>
#define maxn 1000
#define INF (1<<31)-1
using namespace std;
struct Edge
{
int from,to,cap,flow;
Edge(int u,int v,int c,int f):
from(u),to(v),cap(c),flow(f) {}
};
struct Dinic
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
int d[maxn];
int cur[maxn];
bool vis[maxn];
void init(int n)
{
for (int i=0; i<n; i++)
G[i].clear();
edges.clear();
}
void Addedge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BFS()
{
memset(vis,false,sizeof(vis));
for (int i=0; i<n; i++) d[i] = INF;
d[s] = 0; vis[s] = true;
queue<int> Q;
Q.push(s);
while (!Q.empty())
{
int x = Q.front();
Q.pop();
for (int i=0; i<G[x].size(); i++)
{
Edge e = edges[G[x][i]];
if (!vis[e.to] && e.cap>e.flow)
{
vis[e.to] = true;
d[e.to] = d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x,int a)
{
if (x == t || a == 0)
return a;
int flow = 0,f;
for (int i=cur[x]; i<G[x].size(); i++)
{
Edge& e = edges[G[x][i]];
if (d[e.to] == d[x]+1 && (f = DFS(e.to,min(a,e.cap-e.flow))) > 0)
{
e. flow += f;
edges[G[x][i]^1].flow -= f;
flow += f;
a -= f;
if (a == 0)
break;
}
}
return flow;
}
bool OKA()
{
for (int i=0; i<G[s].size(); i++)
{
Edge e = edges[G[s][i]];
if (e.cap!=e.flow)
return false;
}
return true;
}
bool OKB(int R,int C)
{
for (int j=R+1; j<=R+C; j++)
{
Edge& e = edges[G[j][0]];
if (e.cap!=e.flow)
return false;
}
return true;
}
void Maxflow(int t,int R,int C)
{
int flow = 0;
while (BFS())
{
memset(cur,0,sizeof(cur));
flow += DFS(s,INF);
}
cout<<"Matrix "<<t<<endl;
if (OKA() && OKB(R,C))
{
for (int i=1; i<=R; i++)
{
int j;
for (j=1; j<G[i].size()-1; j++)
cout<<edges[G[i][j]].flow+1<<' ';
cout<<edges[G[i][j]].flow+1<<endl;
}
}
cout<<endl;
}
};
int main()
{
Dinic aa;
int T,R,C,tmp;
int a[30],b[30],c[30],d[30];
#ifndef ONLINE_JUDGE
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
#endif
cin>>T;
tmp = T;
while (T>0)
{
T--;
aa.init(maxn);
cin>>R>>C;
for (int i=1; i<=R; i++) cin>>a[i];
for (int i=1; i<=C; i++) cin>>b[i];
for (int i=1; i<=R; i++) c[i] = a[i]-a[i-1]-C;
for (int i=1; i<=C; i++) d[i] = b[i]-b[i-1]-R;
for (int i=1; i<=R; i++)
aa.Addedge(0,i,c[i]);
for (int i=1; i<=C; i++)
aa.Addedge(R+i,R+C+1,d[i]);
for (int i=1; i<=R; i++)
for (int j=1; j<=C; j++)
aa.Addedge(i,R+j,19);
aa.s = 0; aa.t = R+C+1;
aa.Maxflow(tmp-T,R,C);
}
return 0;
}
UVA - 11082 Matrix Decompressing的更多相关文章
- UVa 11082 Matrix Decompressing(最大流)
不想吐槽了..sample input 和sample output 完全对不上...调了一个晚上...不想说什么了... -------------------------------------- ...
- [题解]UVa 11082 Matrix Decompressing
开始眨眼一看怎么也不像是网络流的一道题,再怎么看也觉得像是搜索.不过虽然这道题数据范围很小,但也不至于搜索也是可以随随便便就可以过的.(不过这道题应该是special judge,因为一题可以多解而且 ...
- UVa 11082 Matrix Decompressing - 网络流
开始眨眼一看怎么也不像是网络流的一道题,再怎么看也觉得像是搜索.不过虽然这道题数据范围很小,但也不至于搜索也是可以随随便便就可以过的.(不过这道题应该是special judge,因为一题可以多解而且 ...
- UVa 11082 - Matrix Decompressing(最大流)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 11082 Matrix Decompressing 矩阵解压(最大流,经典)
题意: 知道矩阵的前i行之和,和前j列之和(任意i和j都可以).求这个矩阵.每个格子中的元素必须在1~20之间.矩阵大小上限20*20. 思路: 这么也想不到用网络流解决,这个模型很不错.假设这个矩阵 ...
- UVA - 11082 Matrix Decompressing(最大流+行列模型)
题目大意:给出一个R行C列的矩阵,如今给出他的前1-R行和 && 前1-C列和,问这个矩阵原来是如何的,要求每一个元素大小在1-20之间 解题思路:将每一行连接到超级源点,容量为该行的 ...
- UVA - 11082 Matrix Decompressing (最大流,技巧)
很经典的网络流模型,行编号和列编号分别看成一个点,行和列和分别看出容量,一个点(x,y)看出是一条边,边的容量下界是1,所以先减去1,之后在加上就好了. 建图的时候注意分配好编号,解从残留网络中的边找 ...
- uva 11082 Matrix Decompressing 【 最大流 】
只看题目的话~~怎么也看不出来是网络流的题目的说啊~~~~ 建图好神奇~~ 最开始不懂---后来看了一下这篇-- http://www.cnblogs.com/AOQNRMGYXLMV/p/42807 ...
- uva Matrix Decompressing (行列模型)
Matrix Decompressing 题目: 给出一个矩阵的前i行,前j列的和.要求你求出满足的矩阵. 矩阵的数范围在[1,20]. 一開始就坑在了这里.没读细致题目. 囧... 事 ...
随机推荐
- C++函数模板例子
//C++函数模板实例 #include <iostream>template <class Any>void Swap(Any &a, Any &b); in ...
- 使用mysql导入数据时关掉binlog
在my.cnf中注释掉 log-bin=bin-log参数然后重启数据库
- spring MVC (学习笔记)
web.xml 相关配置 <?xml version="1.0" encoding="UTF-8"?><web-app xmlns=" ...
- Java程序员从笨鸟到菜鸟之(十四)Html基础积累总结(上)
本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 注:由于本文内含有大量html标签,所以在排版上有些困难,所以排版有点难看,请大家见谅 ...
- xamarin.android searchview的一些用法
前言 searchview是安卓常用的搜索控件,网上有很多关于searchview都是java的,所以我参看xamaroin官网的一些demo总结一些方法. 导读 1.如何创建一个searchview ...
- jQuery 怎么获取对象
1.JQuery的核心的一些方法 each(callback) '就像循环 $("Element").length; ‘元素的个数,是个属性 $("Element&quo ...
- Linux时间子系统之(一):时间的基本概念【转】
本文转载自:http://www.wowotech.net/timer_subsystem/time_concept.html 本文使用Q & A的方式来和大家以前探讨一下时间的基本概念 一. ...
- IntelliJ IDEA 运行错误:java: Compilation failed: internal java compiler error
错误:java: Compilation failed: internal java compiler error 解决的方法: 文件 --> 设置 : 若没有模块,点击右边的把自己项目的模块添 ...
- Swift语言学习(三)基础操作符
操作符是用于检测.更改或者组合值的特殊符号或短语.例如,加法操作符 (+) 将两个数字加到一起 (如 let i = 1 + 2).更复杂的例子包括逻辑与操作符 && (如 if en ...
- DFS Used%: NaN%问题
一.问题描述: [root@master sbin]# hdfs dfsadmin -report Configured Capacity: 0 (0 B) Present Capacity: 0 ( ...