• bzoj3698 XWW的难题


    题意:给你个n * n的实数矩阵,你需要把它中的每个数上/下取整,并满足如下条件:

    每行最后一个数等于前面的和。

    每列最后一个数等于前面的和。

    n行n列的那个元素始终为0,不予考虑。

    求满足条件下矩阵中元素的最大总和是多少。

    解:

    首先假设全部下取整。

    s->行->列->t连边,可以发现每条边都有上下界。

    有源汇有上下界最大流。

    出来的最大流*3就是答案。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <queue>
      4 #include <cstring>
      5 
      6 const int N = 210, M = 1000010, INF = 0x3f3f3f3f;
      7 
      8 struct Edge {
      9     int nex, v, c;
     10 }edge[M << 1]; int top = 1;
     11 
     12 int e[N], d[N], ot[N];
     13 std::queue<int> Q;
     14 
     15 inline void add(int x, int y, int z) {
     16     top++;
     17     edge[top].v = y;
     18     edge[top].c = z;
     19     edge[top].nex = e[x];
     20     e[x] = top;
     21 
     22     top++;
     23     edge[top].v = x;
     24     edge[top].c = 0;
     25     edge[top].nex = e[y];
     26     e[y] = top;
     27     return;
     28 }
     29 
     30 inline bool BFS(int s, int t) {
     31     memset(d, 0, sizeof(d));
     32     d[s] = 1;
     33     Q.push(s);
     34     while(!Q.empty()) {
     35         int x = Q.front();
     36         Q.pop();
     37         for(int i = e[x]; i; i = edge[i].nex) {
     38             int y = edge[i].v;
     39             if(!edge[i].c || d[y]) {
     40                 continue;
     41             }
     42             d[y] = d[x] + 1;
     43             Q.push(y);
     44         }
     45     }
     46     return d[t];
     47 }
     48 
     49 int DFS(int x, int t, int maxF) {
     50     if(x == t) {
     51         return maxF;
     52     }
     53     int ans = 0;
     54     for(int i = e[x]; i; i = edge[i].nex) {
     55         int y = edge[i].v;
     56         if(!edge[i].c || d[x] + 1 != d[y]) {
     57             continue;
     58         }
     59         int temp = DFS(y, t, std::min(edge[i].c, maxF - ans));
     60         if(!temp) {
     61             d[y] = INF;
     62         }
     63         ans += temp;
     64         edge[i].c -= temp;
     65         edge[i ^ 1].c += temp;
     66         if(ans == maxF) {
     67             break;
     68         }
     69     }
     70     return ans;
     71 }
     72 
     73 inline int solve(int s, int t) {
     74     int ans = 0;
     75     while(BFS(s, t)) {
     76         ans += DFS(s, t, INF);
     77     }
     78     return ans;
     79 }
     80 
     81 int main() {
     82     int n;
     83     scanf("%d", &n);
     84     int s = n * 2 + 1, t = n * 2 + 2, ss = n * 2 + 3, tt = n * 2 + 4;
     85     for(int i = 1; i <= n; i++) {
     86         for(int j = 1; j <= n; j++) {
     87             double y;
     88             scanf("%lf", &y);
     89             int x = (int)(y);
     90             if(i < n && j < n) {
     91                 // add (i, n + j, x)
     92                 ot[i] += x;
     93                 ot[n + j] -= x;
     94             }
     95             else if(i < n) {
     96                 // add (s, i, x)
     97                 ot[s] += x;
     98                 ot[i] -= x;
     99             }
    100             else if(j < n) {
    101                 // add(n + j, t, x)
    102                 ot[n + j] += x;
    103                 ot[t] -= x;
    104             }
    105             if(x < y) {
    106                 if(i < n && j < n) {
    107                     add(i, n + j, 1);
    108                 }
    109                 else if(i < n) {
    110                     add(s, i, 1);
    111                 }
    112                 else if(j < n) {
    113                     add(n + j, t, 1);
    114                 }
    115             }
    116         }
    117     }
    118     int sum = 0;
    119     for(int i = 1; i <= t; i++) {
    120         if(ot[i] > 0) {
    121             add(i, tt, ot[i]);
    122         }
    123         else if(ot[i] < 0) {
    124             add(ss, i, -ot[i]);
    125             sum -= ot[i];
    126         }
    127     }
    128     add(t, s, INF);
    129 
    130     int ans = solve(ss, tt);
    131     if(ans != sum) {
    132         puts("No");
    133         return 0;
    134     }
    135 
    136     for(int i = e[ss]; i; i = edge[i].nex) {
    137         edge[i].c = edge[i ^ 1].c = 0;
    138     }
    139     for(int i = e[tt]; i; i = edge[i].nex) {
    140         edge[i].c = edge[i ^ 1].c = 0;
    141     }
    142     //edge[top].c = edge[top - 1].c = 0;
    143 
    144     ans = solve(s, t);
    145     //printf("ans + cost %d + %d 
    ", ans * 3, cost);
    146     printf("%d", ans * 3);
    147 
    148     return 0;
    149 }
    AC代码
  • 相关阅读:
    点击滚动到任意位置
    设置滚动条
    突破浏览器限制字体大小不能低于12px的限制
    font-family 字体及各大主流网站对比
    可视区尺寸改变的时候,重绘Echarts
    <input />
    switch (xx) { case xx: break ......}
    让页面随浏览器的窗口大小缩放而缩放
    对后端返回的 html 标签不识别的解决办法
    html 标签分类:块级元素、内联元素 ......
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10104259.html
Copyright © 2020-2023  润新知