Mlxa

TEAMBOOK min-cost-max-flow (задача о назначениях)

Nov 1st, 2019
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.81 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using long_type = long long;
  3. #define long long_type
  4. #define all(x) begin(x), end(x)
  5. using namespace std;
  6. mt19937 rnd;
  7.  
  8. struct edge {
  9.     int v, u, c, f, w, r;
  10.     edge(int _v, int _u, int _c, int _w, int _r) :
  11.         v(_v),
  12.         u(_u),
  13.         c(_c),
  14.         f(0),
  15.         w(_w),
  16.         r(_r) {}
  17. };
  18.  
  19. const int max_n     = 604;
  20. const int source    = max_n - 1;
  21. const int sink      = max_n - 2;
  22. const int inf       = 0x3f3f3f3f;
  23.  
  24. vector<edge> g[max_n];
  25.  
  26. void add_edge(int v, int u, int c, int w) {
  27.     g[v].emplace_back(v, u, c, w, (int)g[u].size());
  28.     g[u].emplace_back(u, v, 0, -w, (int)g[v].size() - 1);
  29. }
  30.  
  31. int dist[max_n];
  32. edge *par[max_n];
  33. bool used[max_n];
  34.  
  35. void fb(int lim) {
  36.     fill(all(dist), inf);
  37.     fill(all(par), nullptr);
  38.     fill(all(used), false);
  39.     dist[source] = 0;
  40.     deque<int> q;
  41.     q.push_back(source);
  42.     used[source] = true;
  43.    
  44.     while (q.size()) {
  45.         int v = q.front();
  46.         q.pop_front();
  47.         used[v] = false;
  48.         for (edge &e : g[v]) {
  49.             if (e.c - e.f < lim) {
  50.                 continue;
  51.             }
  52.             if (dist[e.u] > dist[v] + e.w) {
  53.                 dist[e.u] = dist[v] + e.w;
  54.                 par[e.u]  = &e;
  55.                 if (!used[e.u]) {
  56.                     used[e.u] = true;
  57.                     int fr = inf;
  58.                     if (q.size()) {
  59.                         fr = dist[q.front()];
  60.                     }
  61.                     if (dist[e.u] < fr) {
  62.                         q.push_front(e.u);
  63.                     } else {
  64.                         q.push_back(e.u);
  65.                     }
  66.                 }
  67.             }
  68.         }
  69.     }
  70. }
  71.  
  72. vector<edge *> path;
  73.  
  74. void rec_path() {
  75.     path.clear();
  76.     int v = sink;
  77.     while (v != source) {
  78.         assert(par[v]);
  79.         path.push_back(par[v]);
  80.         assert(v == par[v]->u);
  81.         v = par[v]->v;
  82.     }
  83.     reverse(all(path));
  84. }
  85.  
  86. long mcmf() {
  87.     long answer = 0;
  88.     while (1) {
  89.         fb(1);
  90.         if (dist[sink] == inf) {
  91.             break;
  92.         }
  93.         rec_path();
  94.         int min_cap = inf;
  95.         long sum    = 0;
  96.         for (edge *ep : path) {
  97.             min_cap = min(min_cap, ep->c - ep->f);
  98.             sum += ep->w;
  99.         }
  100.         answer += sum * min_cap;
  101.         for (edge *ep : path) {
  102.             edge &e = *ep;
  103.             edge &r = g[e.u][e.r];
  104.             e.f += min_cap;
  105.             r.f -= min_cap;
  106.             assert(e.f <= e.c);
  107.             assert(r.f <= r.c);
  108.         }
  109.     }
  110.     return answer;
  111. }
  112.  
  113. int main() {
  114. #ifdef LC
  115.     assert(freopen("input.txt", "r", stdin));
  116. #else
  117. #define TASK "assignment"
  118.     assert(freopen(TASK ".in", "r", stdin));
  119.     assert(freopen(TASK ".out", "w", stdout));
  120. #endif
  121.     ios::sync_with_stdio(0);
  122.     cin.tie(0);
  123.    
  124.     int n;
  125.     cin >> n;
  126.     for (int i = 1; i <= n; ++i) {
  127.         for (int j = 1; j <= n; ++j) {
  128.             int c;
  129.             cin >> c;
  130.             add_edge(i, n + j, 1, c);
  131.         }
  132.     }
  133.     for (int i = 1; i <= n; ++i) {
  134.         add_edge(source, i, 1, 0);
  135.         add_edge(n + i, sink, 1, 0);
  136.     }
  137.     cout << mcmf() << "\n";
  138.     vector<pair<int, int>> answer;
  139.     for (int i = 1; i <= n; ++i) {
  140.         for (edge e : g[i]) {
  141.             if (e.f == 1) {
  142.                 answer.emplace_back(i, e.u - n);
  143.             }
  144.         }
  145.     }
  146.     for (auto e : answer) {
  147.         cout << e.first << " " << e.second << "\n";
  148.     }
  149.     cerr << "time = " << 1000 * clock() / CLOCKS_PER_SEC << endl;
  150.     return 0;
  151. }
Add Comment
Please, Sign In to add comment