zoukankan      html  css  js  c++  java
  • luogu P4194 矩阵

    嘟嘟嘟


    先二分。
    令二分的值为(mid),则对于每一行都要满足(|sum_{i = 1} ^ {n} (A_{ij} - B_{ij})|),把绝对值去掉,就得到了((sum_{i = 1} ^ {n} A_{ij}) - mid leqslant sum_{i = 1} ^ {n} B_{ij} leqslant (sum_{i = 1} ^ {n} A_{ij}) + mid)。(列同理)
    这就很明显了,因为是网格图,所以每一行每一列看成一个点建立二分图,从源点向每一行连容量为([(sum_{i = 1} ^ {n} A_{ij}) - mid, (sum_{i = 1} ^ {n} A_{ij}) + mid])的边,然后每一列向汇点也这么连边。同时每一行向每一列连容量为([L,R])的边。
    然后跑上下界网络流。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 205;
    const int maxe = 1e6 + 5;
    inline ll read()
    {
      ll ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    inline void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    
    int n, m, l, r, s, t, S, T;
    int a[maxn][maxn], sumn[maxn], summ[maxn];
    struct Edge
    {
      int nxt, to, cap, flow;
    }e[maxe];
    int head[maxn << 1], ecnt = -1;
    In void addEdge(int x, int y, int w)
    {
      e[++ecnt] = (Edge){head[x], y, w, 0};
      head[x] = ecnt;
      e[++ecnt] = (Edge){head[y], x, 0, 0};
      head[y] = ecnt;
    }
    
    int dis[maxn << 1];
    In bool bfs()
    {
      Mem(dis, 0); dis[S] = 1;
      queue<int> q; q.push(S);
      while(!q.empty())
        {
          int now = q.front(); q.pop();
          for(int i = head[now], v; ~i; i = e[i].nxt)
    	{
    	  if(!dis[v = e[i].to] && e[i].cap > e[i].flow)
    	    dis[v] = dis[now] + 1, q.push(v);
    	}
        }
      return dis[T];
    }
    int cur[maxn << 1];
    In int dfs(int now, int res)
    {
      if(now == T || res == 0) return res;
      int flow = 0, f;
      for(int& i = cur[now], v; ~i; i = e[i].nxt)
        {
          if(dis[v = e[i].to] == dis[now] + 1 && (f = dfs(v, min(res, e[i].cap - e[i].flow))) > 0)
    	{
    	  e[i].flow += f; e[i ^ 1].flow -= f;
    	  flow += f; res -= f;
    	  if(res == 0) break;
    	}
        }
      return flow;
    }
    
    
    In int maxflow()
    {
      int flow = 0;
      while(bfs())
        {
          memcpy(cur, head, sizeof(head));
          flow += dfs(S, INF);
        }
      return flow;
    }
    
    int d[maxn << 1], tot = 0;
    In void build(int lim)
    {
      Mem(head, -1); ecnt = -1; Mem(d, 0); tot = 0;
      for(int i = 1; i <= n; ++i)
        {
          int tp = max(sumn[i] - lim, 0);
          d[s] += tp, d[i] -= tp;
          addEdge(s, i, sumn[i] + lim - tp);
        }
      for(int i = 1; i <= m; ++i)
        {
          int tp = max(summ[i] - lim, 0);
          d[t] -= tp, d[i + n] += tp;
          addEdge(i + n, t, summ[i] + lim - tp);
        }
      for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
          {
    	d[i] += l, d[j + n] -= l;
    	addEdge(i, j + n, r - l);
          }
      for(int i = 0; i <= t; ++i)
        if(d[i] >= 0) addEdge(i, T, d[i]), tot += d[i];
        else addEdge(S, i, -d[i]);
      addEdge(t, s, INF);
    }
    
    In bool judge(int x)
    {
      build(x);
      return maxflow() == tot;
    }
    
    int main()
    {
      Mem(head, -1);
      n = read(), m = read(); s = 0, t = n + m + 1;
      S = t + 1, T = t + 2;
      for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j) a[i][j] = read();
      for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j) sumn[i] = sumn[i] + a[i][j];
      for(int j = 1; j <= m; ++j)
        for(int i = 1; i <= n; ++i) summ[j] = summ[j] + a[i][j];
      l = read(), r = read();
      int L = 0, R = 1e8;
      while(L < R)
        {
          int mid = (L + R) >> 1;
          if(judge(mid)) R = mid;
          else L = mid + 1;
        }
      write(L), enter;
      return 0;
    }
    
  • 相关阅读:
    加入创业公司有什么利弊
    Find Minimum in Rotated Sorted Array II
    Search in Rotated Sorted Array II
    Search in Rotated Sorted Array
    Find Minimum in Rotated Sorted Array
    Remove Duplicates from Sorted Array
    Spiral Matrix
    Spiral Matrix II
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/mrclr/p/10816846.html
Copyright © 2011-2022 走看看