zoukankan      html  css  js  c++  java
  • UVa 11082 Matrix Decompressing (网络流)

    题意:给定一个矩阵的每行每列的前缀和,矩阵的元素是1-20,求这个矩阵。

    析:一个网络流题,首先先把每个点的数减1,那么元素就成了0-19,这样就是一个普通的网络流了,建立一个源点和汇点,源点向每行连一条边,

    汇点向每列连一条边,每个行向每个列连一条容量为19的边,其他的边都是相应的容量。最后跑一次最大流就行了。

    代码如下:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <cmath>
    #include <stack>
    #include <sstream>
    #define debug() puts("++++");
    #define gcd(a, b) __gcd(a, b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define freopenr freopen("in.txt", "r", stdin)
    #define freopenw freopen("out.txt", "w", stdout)
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const double inf = 0x3f3f3f3f3f3f;
    const double PI = acos(-1.0);
    const double eps = 1e-5;
    const int maxn = 500 + 10;
    const int mod = 1e6;
    const int dr[] = {-1, 0, 1, 0};
    const int dc[] = {0, 1, 0, -1};
    const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
    int n, m;
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    inline bool is_in(int r, int c){
      return r >= 0 && r < n && c >= 0 && c < m;
    }
    struct Edge{
      int from, to, cap, flow;
    };
    
    struct Dinic{
      int n, m, s, t;
      vector<Edge> edges;
      vector<int> G[maxn];
      bool vis[maxn];
      int d[maxn];
      int cur[maxn];
    
      void init(){
        edges.clear();
        for(int i = 0; i < maxn; ++i)  G[i].clear();
      }
    
      bool bfs(){
        memset(vis, 0, sizeof vis);
        queue<int> q;
        q.push(s);
        d[s] = 0;  vis[s] = true;
        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] = 1;
              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[x] + 1 == d[e.to] && (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)  break;
          }
        }
        return flow;
      }
    
      int maxflow(int s, int t){
        this->s = s;  this->t = t;
        int flow = 0;
        while(bfs()){
          memset(cur, 0, sizeof cur);
          flow += dfs(s, INF);
        }
        return flow;
      }
    
      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);
      }
    };
    int a[maxn], b[maxn];
    Dinic dinic;
    
    void solve(){
      dinic.init();
      int s = 455;
      int t = 456;
      a[0] = b[0] = 0;
      for(int i = 1; i <= n; ++i)  dinic.addEdge(s, i, a[i]-a[i-1]-m);
      for(int i = n+1; i <= m+n; ++i)  dinic.addEdge(i, t, b[i-n]-b[i-1-n]-n);
      for(int i = 1; i <= n; ++i)
        for(int j = n+1; j <= m+n; ++j)
          dinic.addEdge(i, j, 19);
    
      dinic.maxflow(s, t);
      for(int i = 1; i <= n; ++i)
        for(int j = n+1; j <= m+n; ++j){
          for(int k = 0; k < dinic.G[i].size(); ++k){
            Edge&e = dinic.edges[dinic.G[i][k]];
            if(e.to == j){
                printf("%d%c", e.flow+1, j == m+n ? '
    ' : ' ');
                break;
            }
          }
        }
    }
    
    int main(){
      int T;  cin >> T;
      for(int kase = 1; kase <= T; ++kase){
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; ++i)  scanf("%d", a+i);
        for(int i = 1; i <= m; ++i)  scanf("%d", b+i);
        printf("Matrix %d
    ", kase);
        solve();
        if(kase < T)  puts("");
      }
      return 0;
    }
    
  • 相关阅读:
    HDU4366 Successor 线段树+预处理
    POJ2823 Sliding Window 单调队列
    HDU寻找最大值 递推求连续区间
    UVA846 Steps 二分查找
    HDU3415 Max Sum of MaxKsubsequence 单调队列
    HDU时间挑战 树状数组
    UVA10168 Summation of Four Primes 哥德巴赫猜想
    UESTC我要长高 DP优化
    HDUChess 递推
    HDU4362 Dragon Ball DP+优化
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/6415936.html
Copyright © 2011-2022 走看看