Goldsmith94

GCJ 2017 Round 2 Roller Coaster Scheduling

May 6th, 2019
340
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.59 KB | None | 0 0
  1. #include <algorithm>
  2. #include <climits>
  3. #include <cstring>
  4. #include <iomanip>
  5. #include <iostream>
  6. #include <map>
  7. #include <numeric>
  8. #include <queue>
  9. #include <random>
  10. #include <set>
  11. #include <stack>
  12. #include <string>
  13. #include <utility>
  14. #include <vector>
  15.  
  16. using namespace std;
  17.  
  18. #ifdef TEST
  19. #define CERR(str)        \
  20.   do {                   \
  21.     cerr << str << endl; \
  22.   } while (false)
  23. #else
  24. #define CERR(str) \
  25.   do {            \
  26.   } while (false)
  27. #define endl '\n'
  28. #endif
  29.  
  30. #define eps 1e-9
  31.  
  32. #define ZERO(a) memset(a, 0, sizeof(a))
  33. #define INTINF(a) memset(a, 0x3f, sizeof(a))
  34. #define INTINFVAR(a) memset(&a, 0x3f, sizeof(a))
  35. #define DOUBLEINF(a) memset(a, 0x7f, sizeof(a))
  36. #define DOUBLEINFVAR(a) memset(&a, 0x7f, sizeof(a))
  37. #define INTNEG(a) memset(a, -1, sizeof(a))
  38. #define INTNEGVAR(a) memset(&a, -1, sizeof(a))
  39. #define DOUBLENEG(a) memset(a, 0xfe, sizeof(a))
  40. #define DOUBLENEGVAR(a) memset(&a, 0xfe, sizeof(a))
  41. #define ALL(v) v.begin(), v.end()
  42. #define COPY(src, dest) memcpy(dest, src, sizeof(src))
  43. #define FOR(i, a, b) for (int i = a; i < (b); i++)
  44. #define FORb(i, a, b, extraCondition) \
  45.   for (int i = a; i < (b) && (extraCondition); i++)
  46. #define REP(n) FOR(randomVariableName, 0, n)
  47. #define FORd(i, a, b) for (int i = (b)-1; i >= a; i--)
  48. #define FORdb(i, a, b, extraCondition) \
  49.   for (int i = (b)-1; i >= (a) && (extraCondition); i--)
  50. #define MIN(a, b) a = min((a), b)
  51. #define MAX(a, b) a = max((a), (b))
  52.  
  53. typedef long long int ll;
  54. typedef pair<int, int> pp;
  55.  
  56. int T;
  57.  
  58. // Taken from
  59. // https://github.com/kth-competitive-programming/kactl/blob/master/content/graph/MinCostMaxFlow.h
  60. // I have no idea how it works, this is not an algorithm I put in any effort to
  61. // understanding yet so just took a good implementation
  62. /**
  63.  * Author: Stanford
  64.  * Date: Unknown
  65.  * Source: Stanford Notebook
  66.  * Description: Min-cost max-flow. cap[i][j] != cap[j][i] is allowed; double
  67.  * edges are not. If costs can be negative, call setpi before maxflow, but note
  68.  * that negative cost cycles are not supported. To obtain the actual flow, look
  69.  * at positive values only. Status: Tested on kattis mincostmaxflow Time:
  70.  * Approximately O(E^2)
  71.  */
  72. #define rep(i, a, b) for (int i = a; i < (b); ++i)
  73. #define trav(a, x) for (auto& a : x)
  74. #define all(x) begin(x), end(x)
  75. #define sz(x) (int)(x).size()
  76. typedef long long ll;
  77. typedef pair<int, int> pii;
  78. typedef vector<int> vi;
  79.  
  80. #include <cassert>
  81. #include <ext/pb_ds/priority_queue.hpp>
  82.  
  83. const ll INF = numeric_limits<ll>::max() / 4;
  84. typedef vector<ll> VL;
  85.  
  86. struct MCMF {
  87.   int N;
  88.   vector<vi> ed, red;
  89.   vector<VL> cap, flow, cost;
  90.   vi seen;
  91.   VL dist, pi;
  92.   vector<pii> par;
  93.  
  94.   MCMF(int N)
  95.       : N(N),
  96.         ed(N),
  97.         red(N),
  98.         cap(N, VL(N)),
  99.         flow(cap),
  100.         cost(cap),
  101.         seen(N),
  102.         dist(N),
  103.         pi(N),
  104.         par(N) {}
  105.  
  106.   void addEdge(int from, int to, ll cap, ll cost) {
  107.     this->cap[from][to] = cap;
  108.     this->cost[from][to] = cost;
  109.     ed[from].push_back(to);
  110.     red[to].push_back(from);
  111.   }
  112.  
  113.   void path(int s) {
  114.     fill(all(seen), 0);
  115.     fill(all(dist), INF);
  116.     dist[s] = 0;
  117.     ll di;
  118.  
  119.     __gnu_pbds::priority_queue<pair<ll, int>> q;
  120.     vector<decltype(q)::point_iterator> its(N);
  121.     q.push({0, s});
  122.  
  123.     auto relax = [&](int i, ll cap, ll cost, int dir) {
  124.       ll val = di - pi[i] + cost;
  125.       if (cap && val < dist[i]) {
  126.         dist[i] = val;
  127.         par[i] = {s, dir};
  128.         if (its[i] == q.end())
  129.           its[i] = q.push({-dist[i], i});
  130.         else
  131.           q.modify(its[i], {-dist[i], i});
  132.       }
  133.     };
  134.  
  135.     while (!q.empty()) {
  136.       s = q.top().second;
  137.       q.pop();
  138.       seen[s] = 1;
  139.       di = dist[s] + pi[s];
  140.       trav(i, ed[s]) if (!seen[i])
  141.           relax(i, cap[s][i] - flow[s][i], cost[s][i], 1);
  142.       trav(i, red[s]) if (!seen[i]) relax(i, flow[i][s], -cost[i][s], 0);
  143.     }
  144.     rep(i, 0, N) pi[i] = min(pi[i] + dist[i], INF);
  145.   }
  146.  
  147.   pair<ll, ll> maxflow(int s, int t) {
  148.     ll totflow = 0, totcost = 0;
  149.     while (path(s), seen[t]) {
  150.       ll fl = INF;
  151.       for (int p, r, x = t; tie(p, r) = par[x], x != s; x = p)
  152.         fl = min(fl, r ? cap[p][x] - flow[p][x] : flow[x][p]);
  153.       totflow += fl;
  154.       for (int p, r, x = t; tie(p, r) = par[x], x != s; x = p)
  155.         if (r)
  156.           flow[p][x] += fl;
  157.         else
  158.           flow[x][p] -= fl;
  159.     }
  160.     rep(i, 0, N) rep(j, 0, N) totcost += cost[i][j] * flow[i][j];
  161.     return {totflow, totcost};
  162.   }
  163.  
  164.   // If some costs can be negative, call this before maxflow:
  165.   void setpi(int s) {  // (otherwise, leave this out)
  166.     fill(all(pi), INF);
  167.     pi[s] = 0;
  168.     int it = N, ch = 1;
  169.     ll v;
  170.     while (ch-- && it--)
  171.       rep(i, 0, N) if (pi[i] != INF) trav(
  172.           to, ed[i]) if (cap[i][to]) if ((v = pi[i] + cost[i][to]) < pi[to])
  173.           pi[to] = v,
  174.           ch = 1;
  175.     assert(it >= 0);  // negative cost cycle
  176.   }
  177. };
  178.  
  179. int main() {
  180. #ifndef TEST
  181.   ios_base::sync_with_stdio(false);
  182.   cin.tie(0);
  183.   cerr.setstate(ios_base::failbit);
  184. #endif
  185.   cin >> T;
  186.   FOR(CASE, 1, T + 1) {
  187.     cout << "Case #" << CASE << ": ";
  188.     int N, C, M;
  189.     cin >> N >> C >> M;
  190.     vector<int> ticketsA(N, 0), ticketsB(N, 0);
  191.     REP(M) {
  192.       int P, B;
  193.       cin >> P >> B;
  194.       P--;
  195.       if (B == 1)
  196.         ticketsA[P]++;
  197.       else
  198.         ticketsB[P]++;
  199.     }
  200.     MCMF g(2 * N + 2);
  201.     const int source = 2 * N, sink = 2 * N + 1;
  202.     bool bIteratedOver = false;
  203.     FOR(i, 0, N) {
  204.       if (ticketsA[i]) {
  205.         g.addEdge(source, i, ticketsA[i], 0);
  206.         FOR(j, 0, N) {
  207.           if (!bIteratedOver && ticketsB[j]) {
  208.             g.addEdge(j + N, sink, ticketsB[j], 0);
  209.           }
  210.           if (i == 0 && j == 0) continue;
  211.           if (ticketsB[j]) {
  212.             g.addEdge(i, j + N, M + 100, i == j);
  213.           }
  214.         }
  215.         bIteratedOver |= true;
  216.       }
  217.     }
  218.  
  219.     auto ret = g.maxflow(source, sink);
  220.     ll flow = ret.first;
  221.     ll cost = ret.second;
  222.     ll rides = M - flow;
  223.     ll promotions = cost;
  224.  
  225.     // // Formula solution
  226.     // int numTicketsA = 0, numTicketsB = 0;
  227.     // FOR(i, 0, N) {
  228.     //   numTicketsA += ticketsA[i];
  229.     //   numTicketsB += ticketsB[i];
  230.     // }
  231.     // int ridesSol = max(numTicketsA, numTicketsB);
  232.     // MAX(ridesSol, ticketsA[0] + ticketsB[0]);
  233.     // int promotionsSol = 0;
  234.     // FOR(i, 0, N) { MAX(promotionsSol, ticketsA[i] + ticketsB[i]); }
  235.     // promotionsSol -= min(ridesSol, promotionsSol);
  236.  
  237.     // Max flow solution
  238.     cout << rides << ' ' << promotions;
  239.  
  240.     // // Formula solution
  241.     // cout << ridesSol << ' ' << promotionsSol << endl;
  242.  
  243.     cout << endl;
  244.   }
  245. }
Advertisement
Add Comment
Please, Sign In to add comment