Cod sursa(job #2643459)

Utilizator retrogradLucian Bicsi retrograd Data 19 august 2020 21:33:54
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.03 kb
#include <bits/stdc++.h>

using namespace std;


template<int N>
struct Bitset {
  static constexpr int SZ = (N + 63) / 64;
  unsigned long long data[SZ];

  void set() {
    memset(data, 0xff, sizeof(data));
  }

  Bitset operator&(const Bitset<N> oth) const {
    Bitset ret;
    for (int i = 0; i < SZ; ++i)
      ret.data[i] = (data[i] & oth.data[i]);
    return ret;
  }

  void put1(int pos) {
    data[pos / 64] |= (1ULL << (pos % 64));
  }
  void put0(int pos) {
    data[pos / 64] &= ~(1ULL << (pos % 64));
  }
};


template<int N>
int FindFirst(const Bitset<N>& a, const Bitset<N>& b) {
  for (int i = 0; i < a.SZ; ++i)
    if ((a.data[i] & b.data[i]) != 0)
      return 64 * i + __builtin_ctzll(a.data[i] & b.data[i]);
  return N;
}

template<int N>
struct Matcher {
  array<Bitset<N>, N> graph;
  Bitset<N> mr, vis;
  array<int, N> l, r;

  Matcher() { 
    for (int i = 0; i < N; ++i)
      l[i] = r[i] = -1;
    mr.set();
  }

  void AddEdge(int a, int b) {
    graph[a].put1(b);
  }

  bool Match(int node) {
    int vec;
    vec = FindFirst(graph[node], mr);
    if (vec < N) {
      mr.put0(vec);
      l[node] = vec; r[vec] = node;
      return true;
    } 
    while (true) {
      vec = FindFirst(graph[node], vis);
      if (vec >= N) break;
      vis.put0(vec);
      if (Match(r[vec])) {
        l[node] = vec; r[vec] = node;
        return true;
      }
    }
    return false;
  }

  int Solve(int k) {
    bool stop = false;
    int got = 0;
    while (!stop && got < k) {
      vis.set();
      stop = true;
      for (int i = 0; i < N; ++i) {
        if (l[i] == -1 && Match(i)) {
          stop = false;
          ++got;
        }
      }
    }
    return got;
  }
};

int main() {
  ifstream cin("cuplaj.in");
  ofstream cout("cuplaj.out");
  int n, m, k; cin >> n >> m >> k;
  Matcher<10000> mc;
  for (int i = 0; i < k; ++i) {
    int a, b; cin >> a >> b; 
    mc.AddEdge(a - 1, b - 1);
  }
  cout << mc.Solve(n) << '\n';
  for (int i = 0; i < n; ++i) 
    if (mc.l[i] != -1) 
      cout << i + 1 << " " << mc.l[i] + 1 << '\n';
  return 0;
}