开始眨眼一看怎么也不像是网络流的一道题,再怎么看也觉得像是搜索。不过虽然这道题数据范围很小,但也不至于搜索也是可以随随便便就可以过的。(不过这道题应该是special judge,因为一题可以多解而且题目中然而并没有什么要求,所以说可以考虑思考一下这道题有木有什么"套路"之类的通法)

  比如说有这么一组数据

原矩阵

输入

  然后将每一行的和写在每一列对应的行上(很明显有问题)


  然后调整,为了简便先每个向右挪个1(保障不会出现0什么之类的),接着就随便怎么移都可以,只要第一列满足且每一行的和也满足就行了


  (应该发现了上图的"猫腻"吧!)

  故技重施,是第二列满足


  此时第三列应该也是满足的。

  因此,这道题是不是贪心啊?如果您这么认为那么您可以去写一写,反正我是写不出来的,需要考虑的情况似乎还是有点多。不过可以找到代替贪心的东西——最大流。

  源点直接连接每一行的第一个元素,这条弧的容量为这一行的和。每行相邻的两个元素间有一条弧,容量为这一行的和。除此之外,每一列再增加一个元素,这一列的每一个元素都连接这个点,容量为20。到这里,已经可以发现一些不对的地方,知道这个网络流是干什么的已经可以发现了。每一列流向这个"列汇点"的流量就代表矩阵这个位置的值,然而题目中的要求是1~20。如果照这样做的话,会变成0~20。于是可以将所有元素的值减少1(相应的列、行的和减少多少要清楚)。这条边的容量也改为19。"列汇点"也有一条弧到真正的汇点,容量为这一列的和。

  这样跑一趟最大流算法。最大流为这个矩阵所有元素的和。所以每一行的和满足了,每一列的和也满足了。输出的时候加个1就行了。

Code(极其不简洁的代码)

 /**
* uva
* Problem#11082
* Accepted
* Time:20ms
*/
#include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef bool boolean;
#define INF 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
template<typename T>
inline void readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-');
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
} template<typename T>class Matrix{
public:
T *p;
int lines;
int rows;
Matrix():p(NULL){ }
Matrix(int rows, int lines):lines(lines), rows(rows){
p = new T[(lines * rows)];
}
T* operator [](int pos){
return (p + pos * lines);
}
};
#define matset(m, i, s) memset((m).p, (i), (s) * (m).lines * (m).rows) ///map template starts
typedef class Edge{
public:
int end;
int next;
int cap;
int flow;
Edge(const int end = , const int next = , const int cap = , const int flow = ):end(end), next(next), cap(cap), flow(flow){}
}Edge;
typedef class MapManager{
public:
int ce;
Edge *edge;
int *h;
MapManager(){}
MapManager(int points, int limit):ce(){
h = NULL, edge = NULL;
h = new int[(const int)(points + )];
edge = new Edge[(const int)(limit + )];
memset(h, , sizeof(int) * (points + ));
}
inline void addEdge(int from, int end, int cap, int flow){
edge[++ce] = Edge(end, h[from], cap, flow);
h[from] = ce;
}
inline void addDoubleEdge(int from, int end, int cap){
addEdge(from, end, cap, );
addEdge(end, from, cap, cap);
}
Edge& operator [](int pos) {
return edge[pos];
}
void clear(){
delete[] h;
delete[] edge;
ce = ;
}
}MapManager;
#define m_begin(g, i) (g)->h[(i)]
#define m_end(g, i) (g)->edge[(i)].end
#define m_next(g, i) (g)->edge[(i)].next
#define m_cap(g, i) (g)->edge[(i)].cap
#define m_flow(g, i) (g)->edge[(i)].flow
///map template ends int r, c;
int *lines, *rows;
Matrix<int> hj;
MapManager *g; inline void init(){
readInteger(r);
readInteger(c);
lines = new int[(const int)(c + )];
rows = new int[(const int)(r + )];
hj = Matrix<int>(r + , c + );
for(int i = , last = , a; i <= r; i++){
readInteger(a);
rows[i] = a - last - c;
last = a;
}
for(int i = , last = , a; i <= c; i++){
readInteger(a);
lines[i] = a - last - r;
last = a;
}
} int s, t, sizee; //源,汇,点数 inline int iom(int x, int y){ return (x - ) * c + y; } inline void build(){
s = , t = r * c + c + , sizee = t + ;
g = new MapManager(sizee, sizee * + );
for(int i = ; i < r; i++)
g->addDoubleEdge(s, i * c + , rows[i + ]);
for(int i = ; i <= c; i++)
g->addDoubleEdge(r * c + i, t, lines[i]);
for(int i = ; i <= r; i++){
for(int j = ; j <= c; j++){
if(j < c)
g->addDoubleEdge(iom(i, j), iom(i, j + ), rows[i]);
g->addDoubleEdge(iom(i, j), r * c + j, );
hj[i][j] = g->ce - ;
}
}
} int* divs;
boolean* visited;
queue<int> que; inline boolean getDivs(){
memset(visited, false, sizeof(boolean) * sizee);
que.push(s);
divs[s] = ;
visited[s] = true;
while(!que.empty()){
int e = que.front();
que.pop();
for(int i = m_begin(g, e); i != ; i = m_next(g, i)){
int& eu = m_end(g, i);
if(!visited[eu] && (*g)[i].cap > (*g)[i].flow){
visited[eu] = true;
divs[eu] = divs[e] + ;
que.push(eu);
}
}
}
return visited[t];
} int blockedflow(int node, int minf){
if(node == t || minf == ) return minf;
int f, flow = ;
for(int i = m_begin(g, node); i != ; i = m_next(g, i)){
int& e = m_end(g, i);
if(divs[e] == divs[node] + && (f = (blockedflow(e, min(minf, (*g)[i].cap - (*g)[i].flow)))) > ){
flow += f;
(*g)[i].flow += f;
(*g)[(i & ) ? (i + ) : (i - )].flow -= f;
minf -= f;
if(minf == ) break;
}
}
return flow;
} inline void maxflow(){
while(getDivs()){
blockedflow(, INF);
}
} inline void solve(){
visited = new boolean[sizee];
divs = new int[sizee];
maxflow();
for(int i = ; i <= r; i++){
for(int j = ; j <= c; j++){
printf("%d ", (*g)[hj[i][j]].flow + );
}
putchar('\n');
}
} inline void clearAll(){
delete[] visited;
delete[] divs;
delete[] lines;
delete[] rows;
delete[] hj.p;
delete[] g;
} int kase;
int main(){
readInteger(kase);
for(int k = ; k <= kase; k++){
init();
printf("Matrix %d\n", k);
build();
solve();
putchar('\n');
clearAll();
}
return ;
}

[题解]UVa 11082 Matrix Decompressing的更多相关文章

  1. UVa 11082 Matrix Decompressing(最大流)

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

  2. UVA - 11082 Matrix Decompressing

    2. B - Matrix Decompressing 题意:定义一个R*C的正整数矩阵(1<=R,C<=20),设Ai为前i行所有元素之和,Bi为前i列所有元素之和. 题目已知R,C和数 ...

  3. UVa 11082 Matrix Decompressing - 网络流

    开始眨眼一看怎么也不像是网络流的一道题,再怎么看也觉得像是搜索.不过虽然这道题数据范围很小,但也不至于搜索也是可以随随便便就可以过的.(不过这道题应该是special judge,因为一题可以多解而且 ...

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

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

  5. uva 11082 Matrix Decompressing 【 最大流 】

    只看题目的话~~怎么也看不出来是网络流的题目的说啊~~~~ 建图好神奇~~ 最开始不懂---后来看了一下这篇-- http://www.cnblogs.com/AOQNRMGYXLMV/p/42807 ...

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

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

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

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

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

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

  9. uva Matrix Decompressing (行列模型)

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

随机推荐

  1. MongoDB中insert方法、update方法、save方法简单对比

    MongoDB中insert方法.update方法.save方法简单对比 1.update方法 该方法用于更新数据,是对文档中的数据进行更新,改变则更新,没改变则不变. 2.insert方法 该方法用 ...

  2. Python学习二(生成器和八皇后算法)

    看书看到迭代器和生成器了,一般的使用是没什么问题的,不过很多时候并不能用的很习惯 书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个ugly的代码 ...

  3. Android Activity 四种启动模式

    task和back stack(任务和回退栈) 任务启动,task被加入到回退栈的栈顶,返回的时候回退栈的栈顶任务会被弹出,并被销毁,栈中的前一任务恢复运行,当activity销毁是,系统不会保留ac ...

  4. 40、dom以xml结尾的文件

    1.student.xml文件 <?xml version="1.0" encoding="utf-8" ?> <!-- 1.书写根元素(因为 ...

  5. sasscore22

    1.setting 如果不需要支持ie6,7,请在引入setting文件之前,设置$lte7:false;. $lte7: true !default  表示的是是否兼容it6/7 2.css3 是一 ...

  6. 动态设置和访问cxgrid列的Properties(转)

    原文:http://www.cnblogs.com/hnxxcxg/archive/2010/05/24/2940711.html 动态设置和访问cxgrid列的Properties 设置: cxGr ...

  7. mysql存储过程详细教程

    记录mysql存储过程中的关键语法:DELIMITER //  声明语句结束符,用于区分;CREATE PROCEDURE demo_in_parameter(IN p_in int)  声明存储过程 ...

  8. Linux C 开发环境配置

    换了新电脑,重装了Fedora10,所有开发环境都要重新配置啦,开个随笔记录下过程,说不定以后还要用~ 首先Fedora10装好之后是不带 VIM 的,果断安装之: 打开终端,首先 su 命令切换到r ...

  9. Comet4J推技术在SSHE三大框架中应用-linux下亲测可用

    Comet4J(Comet for Java)是一个纯粹基于AJAX(XMLHTTPRequest)的服务器推送框架,消息以JSON方式传递,具备长轮询.长连接.自动选择三种工作模式. 下载地址 co ...

  10. NFC学习 (1)

    NFC Smart Poster: 放入NFC TAG的都是Smart Poster Advantage:  1.在展示动态内容方面有低功耗的优势: 2.容易扩展容量: 3.容易修改内容(修改后台或者 ...