Cod sursa(job #2690896)

Utilizator retrogradLucian Bicsi retrograd Data 26 decembrie 2020 13:30:15
Problema Cuplaj maxim in graf bipartit Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.05 kb
#include <bits/stdc++.h>

using namespace std;
using T = int;

struct Dinic {
  struct Edge { int from, to, nxt; T cap, flow; };
   
  vector<Edge> es;
  vector<int> graph, at, dist, q;
  
  Dinic(int n) : graph(n, -1) {}
  
  int AddEdge(int a, int b, T c) {
    auto add = [&](int a, int b, T c) {
      es.push_back({a, b, graph[a], c, 0});
      graph[a] = es.size() - 1;
    };
    add(a, b, c); add(b, a, 0);
    return es.size() - 2;
  } 
  bool bfs(int src, int dest) {
    dist.assign(graph.size(), -1); q.clear();
    dist[src] = 0; q.push_back(src);
    for (int i = 0; i < (int)q.size(); ++i) {
      int node = q[i];
      for (int ei = graph[node]; ei >= 0; ei = es[ei].nxt) {
        const auto &e = es[ei];
        if (dist[e.to] == -1 && e.flow < e.cap) {
          dist[e.to] = dist[node] + 1;
          q.push_back(e.to);
        }
      }
    }
    return dist[dest] != -1;
  }
  T dfs(int node, int dest, T need) {
    if (!need || node == dest) return need;
    T ret = 0;
    for (int& ei = at[node]; ei != -1; ei = es[ei].nxt) {
      const auto &e = es[ei];
      if (dist[e.to] != dist[node] + 1) continue;
      if (T now = dfs(e.to, dest, min(need, e.cap - e.flow))) {
        es[ ei ].flow += now;
        es[ei^1].flow -= now;
        ret += now; need -= now;
      }
      if (!need) break;
    }
    return ret;
  }
  T Compute(int src, int dest) {
    T ret = 0;
    while (bfs(src, dest)) {
      at = graph;
      ret += dfs(src, dest, numeric_limits<T>::max());
    }
    return ret;
  }
};

int main() {
  ifstream cin("cuplaj.in");
  ofstream cout("cuplaj.out");
  int n, m, k; cin >> n >> m >> k;
  Dinic D(n + m + 2);
  for (int i = 0; i < n + m; ++i) {
    if (i < n) D.AddEdge(n + m, i, 1);
    else D.AddEdge(i, n + m + 1, 1);
  }
  vector<int> es(k);
  for (int i = 0; i < k; ++i) {
    int a, b; cin >> a >> b; --a; --b;
    es[i] = D.AddEdge(a, b + n, 1);
  }
  cout << D.Compute(n + m, n + m + 1) << endl;
  for (int i = 0; i < k; ++i) {
    const auto& e = D.es[es[i]];
    if (e.flow) cout << e.from + 1 << " " << e.to - n + 1 << '\n';
  }
  return 0;
}