zoukankan      html  css  js  c++  java
  • bzoj 3597 [Scoi2014] 方伯伯运椰子

    题目传送门

      传送门

    题目大意

      给定一个费用流,每条边有一个初始流量$c_i$和单位流量费用$d_i$,增加一条边的1单位的流量需要花费$b_i$的代价而减少一条边的1单位的流量需要花费$a_i$的代价。要求最小化总费用减少量和调整次数的比值(至少调整一次)。

      根据基本套路,二分答案,移项,可以得到每条边的贡献。

      设第$i$条边的流量变化量为$m_i$,每次变化花费的平均费用为$w_i$。那么有

    $sum c_id_i - sum (c_i + m_i)d_i + |m_i|(w_i + mid) > 0$

    $sum m_id_i+ |m_i|(w_i + mid) < 0$

      那么二分答案后等于判断是否存在一个增广环的费用和为负。(请手动参见式子脑补边权)。

      然后可以写个spfa。

    Code

      1 /**
      2  * bzoj
      3  * Problem#3597
      4  * Accepted
      5  * Time: 464ms
      6  * Memory: 1720k
      7  */
      8 #include <iostream>
      9 #include <cstdlib>
     10 #include <cstdio>
     11 #include <vector>
     12 #include <queue>
     13 using namespace std;
     14 typedef bool boolean;
     15 
     16 template <typename T>
     17 void pfill(T* pst, const T* ped, T val) {
     18     for ( ; pst != ped; *(pst++) = val);
     19 }
     20 
     21 typedef class Edge {
     22     public:
     23         int ed, nx;
     24         double w;
     25 
     26         Edge(int ed, int nx, double w) : ed(ed), nx(nx), w(w) {    }
     27 } Edge;
     28 
     29 typedef class MapManager {
     30     public:
     31         int* h;
     32         vector<Edge> es;
     33 
     34         MapManager() {    }
     35         MapManager(int n) {
     36             h = new int[(n + 1)];
     37             pfill(h, h + n + 1, -1);
     38         }
     39         ~MapManager() {
     40             delete[] h;
     41             es.clear();
     42         }
     43 
     44         void addEdge(int u, int v, double w) {
     45             es.push_back(Edge(v, h[u], w));
     46             h[u] = (signed) es.size() - 1;
     47         }
     48 
     49         Edge& operator [] (int p) {
     50             return es[p];
     51         }
     52 } MapManager;
     53 
     54 const double dinf = 1e10;
     55 const double eps = 1e-4;
     56 
     57 typedef class Graph {
     58     public:
     59         int n, s;
     60         MapManager g;
     61         
     62         int *cnt;
     63         double *f;
     64         boolean *vis;
     65 
     66         Graph(int n, int s) : n(n), s(s), g(n) {
     67             cnt = new int[(n + 1)];
     68             f = new double[(n + 1)];
     69             vis = new boolean[(n + 1)];
     70             pfill(vis, vis + n + 1, false);
     71         }
     72 
     73         boolean neg_circle() {
     74             static queue<int> que;
     75             pfill(f, f + n + 1, dinf);
     76             pfill(cnt, cnt + n + 1, 0);
     77             f[s] = 0, cnt[s]++;
     78             que.push(s);
     79             while (!que.empty()) {
     80                 int e = que.front();
     81                 que.pop();
     82                 vis[e] = false;
     83                 for (int i = g.h[e], eu; ~i; i = g[i].nx) {    
     84                     eu = g[i].ed;
     85                     double w = f[e] + g[i].w;
     86                     if (w < f[eu]) {
     87                         f[eu] = w, cnt[eu]++;
     88                         if (cnt[eu] > n)
     89                             return true;
     90                         if (!vis[eu]) {
     91                             que.push(eu);
     92                             vis[eu] = true; 
     93                         }
     94                     }
     95                 }
     96             }
     97             return false;
     98         }
     99 } Graph;
    100 
    101 int n, m;
    102 int *u, *v, *a, *b, *c, *d;
    103 double init_ans = 0.0;
    104 
    105 inline void init() {
    106     scanf("%d%d", &n, &m);
    107     u = new int[(m + 1)];
    108     v = new int[(m + 1)];
    109     a = new int[(m + 1)];
    110     b = new int[(m + 1)];
    111     c = new int[(m + 1)];
    112     d = new int[(m + 1)];
    113     for (int i = 1; i <= m; i++) {
    114         scanf("%d%d%d%d%d%d", u + i, v + i, a + i, b + i, c + i, d + i);
    115         init_ans += c[i] * d[i];
    116     }
    117 }
    118 
    119 boolean check(double mid) {
    120     Graph graph(n + 2, n + 1);
    121     MapManager& g = graph.g;
    122     
    123     for (int i = 1; i <= m; i++) {
    124         if (u[i] == n + 1) {
    125             g.addEdge(u[i], v[i], 0);
    126         } else if (c[i]) {
    127             g.addEdge(u[i], v[i], d[i] + b[i] + mid);
    128             g.addEdge(v[i], u[i], -d[i] + a[i] + mid);
    129         } else {
    130             g.addEdge(u[i], v[i], d[i] + b[i] + mid);
    131         }
    132     }
    133 
    134     return graph.neg_circle();
    135 }
    136 
    137 inline void solve() {
    138     double l = 0, r = init_ans, mid;
    139     for (int t = 0; t < 128 && l < r - eps; t++) {
    140         mid = (l + r) / 2;
    141         if (check(mid))
    142             l = mid;
    143         else
    144             r = mid;
    145     }
    146     printf("%.2lf
    ", l);
    147 }
    148 
    149 int main() {
    150     init();
    151     solve();
    152     return 0;
    153 }
    spfa

      然后再讲讲费用流做法。因为不存在负的流量,但是我们知道$c_i' geqslant 0$,因此我们考虑将$m_i$变成$-c_i + m_i'$。

      其中$m_i'$始终非负。可以理解为这个做法就是将所有边的流量先变为0再重新调整。

      对于绝对值的部分稍微处理一下就行了。(之前那个式子脑残取了等,调了半天,sad。。。)

    Code

      1 /**
      2  * bzoj
      3  * Problem#3597
      4  * Accepted
      5  * Time: 1168ms
      6  * Memory: 2004k
      7  */
      8 #include <iostream>
      9 #include <cstdlib>
     10 #include <cstdio>
     11 #include <queue>
     12 #include <cmath>
     13 using namespace std;
     14 typedef bool boolean;
     15 
     16 template <typename T>
     17 void pfill(T* pst, const T* ped, T val) {
     18     for ( ; pst != ped; *(pst++) = val);
     19 }
     20 
     21 typedef class Edge {
     22     public:
     23         int ed, nx, r;
     24         double c;
     25 
     26         Edge(int ed = 0, int nx = 0, int r = 0, double c = 0) : ed(ed), nx(nx), r(r), c(c) {    } 
     27 } Edge;
     28 
     29 typedef class MapManager {
     30     public:
     31         int* h;
     32         vector<Edge> es;
     33 
     34         MapManager() {    }
     35         MapManager(int n) {
     36             h = new int[(n + 1)];
     37             pfill(h, h + n + 1, -1);
     38         }
     39         ~MapManager() {
     40             delete[] h;
     41             es.clear();
     42         }
     43 
     44         void addEdge(int u, int v, int r, double c) {
     45             es.push_back(Edge(v, h[u], r, c));
     46             h[u] = (signed) es.size() - 1;
     47         }
     48 
     49         void addArc(int u, int v, int cap, double c) {
     50             addEdge(u, v, cap, c);
     51             addEdge(v, u, 0, -c);
     52         }
     53 
     54         Edge& operator [] (int p) {
     55             return es[p];
     56         }
     57 } MapManager;
     58 
     59 const signed int inf = (signed) (~0u >> 1);
     60 const double dinf = 1e10;
     61 const double eps = 1e-4;
     62 
     63 template <typename T>
     64 T __abs(T x) {
     65     return (x < 0) ? (-x) : (x);
     66 }
     67 
     68 typedef class Network {
     69     public:
     70         int S, T;
     71         MapManager g;
     72         
     73         int *le;
     74         int *mf;
     75         double *f;
     76         boolean *vis;
     77 
     78         Network() {    }
     79         // be sure T is the last node
     80         Network(int S, int T) : S(S), T(T), g(T) {
     81             f = new double[(T + 1)];
     82             le = new int[(T + 1)];
     83             mf = new int[(T + 1)];
     84             vis = new boolean[(T + 1)];
     85             pfill(vis, vis + T, false);
     86         }
     87         ~Network() {
     88             delete[] f;
     89             delete[] le;
     90             delete[] mf;
     91             delete[] vis;
     92         }
     93 
     94         double spfa() {
     95             double w;
     96             static queue<int> que;
     97             pfill(f, f + T + 1, dinf);
     98             que.push(S);
     99             f[S] = 0, le[S] = -1, mf[S] = inf;
    100             while (!que.empty()) {
    101                 int e = que.front();
    102                 que.pop();
    103                 vis[e] = false; 
    104                 for (int i = g.h[e], eu; ~i; i = g[i].nx) {
    105                     if (!g[i].r)
    106                         continue;
    107                     eu = g[i].ed, w = f[e] + g[i].c;
    108                     if (w < f[eu]) {
    109                         f[eu] = w, le[eu] = i, mf[eu] = min(mf[e], g[i].r);
    110                         if (!vis[eu]) {
    111                             vis[eu] = true;
    112                             que.push(eu);
    113                         }
    114                     }
    115                 }
    116             }
    117             if (__abs(f[T] - dinf) < eps)
    118                 return dinf;
    119             double rt = 0;
    120             for (int p = T, e; ~le[p]; p = g[e ^ 1].ed) {
    121                 e = le[p];
    122                 g[e].r -= mf[T];
    123                 g[e ^ 1].r += mf[T];
    124                 rt += mf[T] * g[e].c;
    125             }
    126             return rt;
    127         }
    128 
    129         double min_cost() {
    130             double rt = 0, delta;
    131             while (__abs((delta = spfa()) - dinf) >= eps) {
    132                 rt += delta;
    133             }
    134             return rt;
    135         }
    136 } Network;
    137 
    138 // S: n + 1, T: n + 2
    139 int n, m;
    140 int *u, *v, *a, *b, *c, *d;
    141 double init_ans = 0.0;
    142 
    143 inline void init() {
    144     scanf("%d%d", &n, &m);
    145     u = new int[(m + 1)];
    146     v = new int[(m + 1)];
    147     a = new int[(m + 1)];
    148     b = new int[(m + 1)];
    149     c = new int[(m + 1)];
    150     d = new int[(m + 1)];
    151     for (int i = 1; i <= m; i++) {
    152         scanf("%d%d%d%d%d%d", u + i, v + i, a + i, b + i, c + i, d + i);
    153         init_ans += c[i] * d[i];
    154     }
    155 }
    156 
    157 boolean check(double mid) {
    158     double cost = 0;
    159     Network network(n + 1, n + 2);
    160     MapManager& g = network.g;
    161     for (int i = 1; i <= m; i++) {
    162         if (u[i] == n + 1) {
    163             g.addArc(u[i], v[i], c[i], 0);
    164         } else {
    165             g.addArc(u[i], v[i], c[i], -(a[i] + mid) + d[i]);
    166             g.addArc(u[i], v[i], inf, b[i] + mid + d[i]);
    167 //            cost += c[i] * (-d[i] + a[i] + mid);
    168             cost += c[i] * (-d[i] + a[i] + mid);
    169         }
    170     }
    171     cost += network.min_cost();
    172     return  cost < 0;
    173 }
    174 
    175 inline void solve() {
    176     double l = 0, r = init_ans, mid;
    177     for (int t = 0; t < 128 && l < r - eps; t++) {
    178         mid = (l + r) / 2;
    179         if (check(mid))
    180             l = mid;
    181         else
    182             r = mid;
    183     }
    184     printf("%.2lf
    ", l);
    185 }
    186 
    187 int main() {
    188     init();
    189     solve();
    190     return 0;
    191 }
  • 相关阅读:
    Java中的线程安全问题
    谈谈你对Spring的理解
    Word 2016问题导致无法创建其他博客账号
    JS中 Cookie、 LocalStorage 与 SessionStorage
    CSDN代码块显示颜色
    Java中创建线程的两种方式
    毕业设计每日博客——第五周1
    毕业设计每日博客--第四周5
    毕业设计每日博客--第四周4
    毕业设计每日博客--第四周3
  • 原文地址:https://www.cnblogs.com/yyf0309/p/10197979.html
Copyright © 2011-2022 走看看