uva Matrix Decompressing (行列模型)

Matrix Decompressing

题目:

   给出一个矩阵的前i行,前j列的和。要求你求出满足的矩阵。矩阵的数范围在[1,20]。

  一开始就坑在了这里。没读仔细题目。囧。。。

  其实这题的模型就是一个网络流的行列模型,跟poj的那题budge一样建图。不过Poj 的那个建图输入麻烦,而这题是裸的,因为已经告诉你了下界为1,上界为20,囧。。。而且poj那题我至今也不知道为什么我会一直超时。T_T

算法:

   行列模型可以转换成网络流的有源汇上下界网络流求解。而行号和列号分别作为顶点。连结超级源汇点就ok了。跑两边最大流,而每条边上的流量+下界流就是结果了。

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;

const int INF = 1 << 20;
const int MAXN = 400 + 10;
struct Edge{
   int from,to,cap,flow;
   Edge(){};
   Edge(int _from,int _to,int _cap,int _flow)
      :from(_from),to(_to),cap(_cap),flow(_flow){};
};
vector<Edge> edges;
vector<int> G[MAXN];
int cur[MAXN],d[MAXN];
int N,M,src,sink,ss,tt;

//////////////////////////////////////

int ans[MAXN][MAXN];

void init(){
   ss = N + M + 2;   tt = ss + 1;
   src = tt + 1; sink = src + 1;
   for(int i = 0;i <= sink + 1;++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));
   int sz = edges.size();
   G[from].push_back(sz - 2);
   G[to].push_back(sz - 1);
}

bool BFS(){
   fill(d,d + sink + 2,-1);
   queue<int> Q;
   Q.push(src);
   d[src] = 0;

   while(!Q.empty()){
       int x = Q.front(); Q.pop();
       for(int i = 0;i < (int)G[x].size();++i){
           Edge& e = edges[G[x][i]];
           if(d[e.to] == -1 && e.cap > e.flow){
               d[e.to] = d[x] + 1;
               Q.push(e.to);
           }
       }
   }

   return d[sink] > 0;
}

int DFS(int x,int a){
    if(x == sink || a == 0)
         return a;

    int flow = 0,f;
    for(int& i = cur[x];i < (int)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;
}

int maxflow(){
   int flow = 0;
   while(BFS()){
       memset(cur,0,sizeof(cur));
       flow += DFS(src,INF);
   }
   return flow;
}

int main()
{
   // freopen("Input.txt","r",stdin);

    int T;
    scanf("%d",&T);
    for(int kase = 1;kase <= T;++kase){
        scanf("%d%d",&N,&M);

        init();

        int sum = 0,x;
        for(int i = 1;i <= N;++i){
            scanf("%d",&x);
            addEdge(ss,i,x - sum);
            sum = x;
        }

        sum = 0;
        for(int i = 1;i <= M;++i){
            scanf("%d",&x);
            addEdge(i+N,tt,x - sum);
            sum = x;
        }

        for(int i = 1;i <= N;++i){
            for(int j = 1;j <= M;++j){
              addEdge(i,sink,1);
              addEdge(i,N + j,19);
              addEdge(src,N + j,1);
            }
        }

        addEdge(tt,ss,INF);

       int flow = maxflow();

        src = ss; sink = tt;

        maxflow();
        printf("Matrix %d\n",kase);

        for(int i = 1;i <= N;++i){
            for(int j = 0;j < (int)G[i].size();++j){
                Edge& e = edges[G[i][j]];
                if(e.from > N||e.to <= N||e.to > N+M) continue;
                ans[e.from][e.to - N] = e.flow + 1;
            }
        }

        for(int i = 1;i <= N;++i){
            for(int j = 1;j <= M;++j)
                printf("%d%c",ans[i][j],j == M ? '\n':' ');
        }
    }
    return 0;
}
时间: 2024-12-25 02:33:24

uva 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 &amp; 最大流的行列模型

题意: 给出一个矩阵前i行的和与前j列的和,(i∈[1,r],j属于[1,c]),每个元素ai,j∈[1,20],请你还原出这个矩阵,保证有解. SOL: 给网络流建模跪了,神一样的建图,如果我我会怎么做呢?...搜索?然而每个元素具有行,列双重相关性...暴力都打不出来吧... 然而我们顺着搜索的方向想,如果每个点的搜索值最终小于这行的和,那么我们应该做什么?增大它!是不是感觉有点增广的想法出来了------>然而我只是瞎BB...事后觉得可以这么想但考场上并不能这么想出来... 考虑它的建图

UVa 11082 Matrix Decompressing(最大流)

不想吐槽了..sample input 和sample output 完全对不上...调了一个晚上...不想说什么了... ------------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vect

UVA Matrix Chain Multiplication

题目如下: Matrix Chain Multiplication Suppose you have to evaluate an expression like A*B*C*D*E where A,B,C,D and E are matrices. Since matrix multiplication is associative, the order in which multiplications are performed is arbitrary. However, the numb

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

UVA-11082 Matrix Decompressing(有上下界的最大流)

题目链接: Matrix Decompressing 题意: 给一个矩阵的每行和每列的和,(给的是前i行或者列的和); 矩阵中每个元素的值在1到20之间,找出这样的一个矩阵: 思路: 把它转化成一个二分图,每行和每列之间连一条弧,然后设置一个源点和一个汇点,源点与行点相连,汇点与列点相连,求一个最大值,当然这是一个有下界的最大流,需要做-1的处理,同时与源汇相连的边也是要处理的;最后求得的反向边+1就是答案了; AC代码: #include <bits/stdc++.h> /*#include

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

[题解]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′),因此想到把矩阵的每行和