zoukankan      html  css  js  c++  java
  • uva11082 Matrix Decompressing

    证明:

    对于每一个X节点,都是只有一个入流,多个出流(分别流向每一个Y节点),显然多个出流的和正好等于入流;同理,对于每一个Y节点,有多个入流(分别来自每一个X节点),只有一个出流,显然多个入流的和等于出流。第一类弧,以每一行所有元素之和为容量;第三类弧,以每一列所有元素之和为容量;第二类弧,最终流量为矩阵中的每一个元素。也就是说,第一类弧分成多个分支,每一个第一类弧都分出一个分支汇到同一个第三类弧。再考虑矩阵:把每一行的和分成多个元素,每一行的和都会分出一个元素排列在同一列,组成这一列的和。只要求出每一个第二类弧的流量,就是求出了矩阵中的每一个元素。

    注意建图技巧

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 50 + 5;
    const int INF = 1000000000;
    
    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 EdmondsKarp {
      int n, m;
      vector<Edge> edges;    // 边数的两倍
      vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
      int a[maxn];           // 当起点到i的可改进量
      int p[maxn];           // 最短路树上p的入弧编号
    
      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);
      }
    
      int Maxflow(int s, int t) {
        int flow = 0;
        for(;;) {
          memset(a, 0, sizeof(a));
          queue<int> Q;
          Q.push(s);
          a[s] = INF;
          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(!a[e.to] && e.cap > e.flow) {
                p[e.to] = G[x][i];
                a[e.to] = min(a[x], e.cap-e.flow);
                Q.push(e.to);
              }
            }
            if(a[t]) break;
          }
          if(!a[t]) break;
          for(int u = t; u != s; u = edges[p[u]].from) {
            edges[p[u]].flow += a[t];
            edges[p[u]^1].flow -= a[t];
          }
          flow += a[t];
        }
        return flow;
      }
    };
    
    EdmondsKarp g;
    int no[maxn][maxn];
    
    int main() {
      int T, R, C, v, kase = 0;
      scanf("%d", &T);
      for(int kase = 1; kase <= T; kase++) {
        scanf("%d%d", &R, &C);
        g.init(R+C+2);                     //初始化  注意R+C+2
        int last = 0;
        for(int i = 1; i <= R; i++) {
          scanf("%d", &v);
          g.AddEdge(0, i, v - last - C); // row sum is v - last //S到行Ai
          last = v;
        }
        last = 0;
        for(int i = 1; i <= C; i++) {
          scanf("%d", &v);
          g.AddEdge(R+i, R+C+1, v - last - R); // col sum is v - last  //用R+j
          last = v;
        }
    
        for(int i = 1; i <= R; i++)
          for(int j = 1; j <= C; j++) {
            g.AddEdge(i, R+j, 19);
            no[i][j] = g.edges.size() - 2; // no[i][j] is the index of arc for cell(i,j)
          }                                //-2是因为加了反向边
        g.Maxflow(0, R+C+1);
    
        printf("Matrix %d
    ", kase);
        for(int i = 1; i <= R; i++) {
          for(int j = 1; j <= C; j++)
            printf("%d ", g.edges[no[i][j]].flow + 1); // we subtracted 1 from every cell
          printf("
    ");
        }
        printf("
    ");
      }
      return 0;
    }
  • 相关阅读:
    Power BI for Office 365(八)共享查询
    Power BI for Office 365(七) Power BI站点
    Power BI for Office 365(六)Power Map简介
    Power BI for Office 365(五)Power View第二部分
    Power BI for Office 365(四)Power View第一部分
    Power BI for Office 365(三)Power Pivot
    Power BI for Office 365(二)Power Query
    java 继承、重载、重写与多态
    Android 热修复方案Tinker(一) Application改造
    阿里最新热修复Sophix与QQ超级补丁和Tinker的实现与总结
  • 原文地址:https://www.cnblogs.com/lqerio/p/9860927.html
Copyright © 2011-2022 走看看