EntropyIncreaser

flow_graph

Jan 26th, 2018
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.22 KB | None | 0 0
  1. #ifndef AC_FLOW_GRAPH
  2. #define AC_FLOW_GRAPH
  3.  
  4. #include <cmath>
  5. #include <cstring>
  6.  
  7. #include <algorithm>
  8. #include <queue>
  9.  
  10. template <class T>
  11. class is_zero {
  12. public:
  13.     bool operator()(const T& x) const;
  14. };
  15.  
  16. template <>
  17. class is_zero<int> {
  18. public:
  19.     bool operator()(const int& x) const {
  20.         return x == 0;
  21.     }
  22. };
  23.  
  24. template <>
  25. class is_zero<double> {
  26. private:
  27.     double eps;
  28.  
  29. public:
  30.     is_zero<double>(double eps) : eps(eps) {}
  31.  
  32.     bool operator()(const double& x) const {
  33.         return fabs(x) < eps;
  34.     }
  35. };
  36.  
  37. template <class WeightT = int, class ZeroPredicator = is_zero<WeightT> >
  38. class flow_graph {
  39. public:
  40.     typedef WeightT            weight_type;
  41.     typedef const weight_type& const_weight_reference;
  42.     typedef weight_type*       weight_array_type;
  43.  
  44. private:
  45.     struct edge {
  46.         int v;
  47.         weight_type w;
  48.         edge *next, *rev;
  49.     };
  50.  
  51.     int v, e;
  52.     edge *pool, *used;
  53.     edge **adj;
  54.     ZeroPredicator zero_predicator;
  55.    
  56.     edge* add_edge(int u, int v, const_weight_reference w) {
  57.         edge* p = used;
  58.         ++used;
  59.         p->v = v;
  60.         p->w = w;
  61.         p->next = adj[u];
  62.         adj[u] = p;
  63.         return p;
  64.     }
  65.  
  66.     bool bfs(int s, int t, int* level) {
  67.         memset(level, -1, sizeof(int) * v);
  68.         std::queue<int> q;
  69.         q.push(s);
  70.         level[s] = 0;
  71.         while (!q.empty()) {
  72.             int u = q.front();
  73.             q.pop();
  74.             for (edge* p = adj[u]; p; p = p->next)
  75.                 if (!zero_predicator(p->w) && level[p->v] == -1) {
  76.                     level[p->v] = level[u] + 1;
  77.                     if (p->v == t)
  78.                         return true;
  79.                     q.push(p->v);
  80.                 }
  81.         }
  82.         return false;
  83.     }
  84.  
  85.     weight_type dfs(int u, int t, weight_type lim, edge** cadj, int* level) {
  86.         if (u == t)
  87.             return lim;
  88.         weight_type flow = 0;
  89.         for (edge*& p = cadj[u]; p; p = p->next)
  90.             if (!zero_predicator(p->w) && level[u] < level[p->v]) {
  91.                 weight_type f = dfs(p->v, t, std::min(p->w, lim), cadj, level);
  92.                 flow += f;
  93.                 lim -= f;
  94.                 p->w -= f;
  95.                 p->rev->w += f;
  96.                 if (zero_predicator(lim))
  97.                     return flow;
  98.             }
  99.         return flow;
  100.     }
  101.    
  102.     weight_type dfs(int u, int t, edge** cadj, int* level) {
  103.         weight_type flow = 0;
  104.         for (edge*& p = cadj[u]; p; p = p->next)
  105.             if (!zero_predicator(p->w) && level[u] < level[p->v]) {
  106.                 weight_type f = dfs(p->v, t, p->w, cadj, level);
  107.                 flow += f;
  108.                 p->w -= f;
  109.                 p->rev->w += f;
  110.             }
  111.         return flow;
  112.     }
  113.  
  114. public:
  115.     flow_graph() {}
  116.  
  117.     flow_graph(int v, int e, ZeroPredicator zero_predicator = is_zero<WeightT>()) : v(v), e(e), zero_predicator(zero_predicator) {
  118.         pool = new edge[e * 2];
  119.         adj = new edge*[v];
  120.         memset(pool, 0, sizeof(edge) * e * 2);
  121.         memset(adj, 0, sizeof(edge*) * v);
  122.         used = pool;
  123.     }
  124.  
  125.     ~flow_graph() {
  126.         delete[] pool;
  127.         delete[] adj;
  128.     }
  129.  
  130.     void link(int u, int v, const_weight_reference w) {
  131.         edge *p = add_edge(u, v, w), *q = add_edge(v, u, 0);
  132.         p->rev = q;
  133.         q->rev = p;
  134.     }
  135.  
  136.     /**
  137.      * Calculate the maximum flow from `s` to `t`. Using the dinic algorithm.
  138.      * time complexity: O(n^2e)
  139.      * example: https://loj.ac/submission/58439
  140.      **/
  141.     weight_type max_flow(int s, int t) {
  142.         int* level = new int[v];
  143.         edge** cadj = new edge*[v];
  144.         weight_type flow = 0;
  145.         while (bfs(s, t, level)) {
  146.             memcpy(cadj, adj, sizeof(edge*) * v);
  147.             flow += dfs(s, t, cadj, level);
  148.         }
  149.         delete[] level;
  150.         delete[] cadj;
  151.         return flow;
  152.     }
  153. };
  154.  
  155. #endif
Advertisement
Add Comment
Please, Sign In to add comment