Cod sursa(job #2981436)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 17 februarie 2023 22:26:58
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.47 kb
#include <cstdio>
#include <memory>
#include <vector>

using namespace std;

class Solver{
private:
  bool match(int k, // always on the right side
	     const vector<vector<int>>& left,
	     const vector<vector<int>>& right,
	     vector<int> &matchOnLeft,
	     vector<int> &matchOnRight,
	     vector<bool> &usedLeft) {
    if (usedLeft[k]) 
      return false;
    
    usedLeft[k] = true;
    
    for (auto v: left[k])
      if (matchOnLeft[v] == -1) {
	matchOnLeft[v] = k;
	matchOnRight[k] = v;
	return true;
      }
    
    for (auto v: left[k]) 
      if (match(matchOnLeft[v],
		left,
		right,
		matchOnLeft,
		matchOnRight,
		usedLeft)) {
	matchOnLeft[v] = k;
	matchOnRight[k] = v;
	return true;
      }
    
    return false;
  }
  void hopcroftKarp(const vector<vector<int>> &left,
		    const vector<vector<int>> &right,
		    vector<tuple<int,int>> &matching) {
    vector<int> matchOnRight((int)left.size(), -1);
    // matchOnRight[node_on_left] = -1 if not matched or a node_on_right such that
    // [node_on_left, node_on_right] is a valid edge
    vector<int> matchOnLeft((int)right.size(), -1);
    // matchOnLeft[node_on_right] = -1 if not matched or a node_on_left such that
    // [node_on_left, node_on_right] is a valid edge

    vector<bool> usedLeft((int)left.size());
    bool improved = false;
    do {
      improved = false;
      fill(usedLeft.begin(), usedLeft.end(), false);
      for (int i = 0; i < (int)left.size(); ++i)
	if (matchOnRight[i] == -1)
	  improved |= match(i, left, right, matchOnLeft, matchOnRight, usedLeft);
    } while (improved);
    
    for (int i = 0; i < (int)left.size(); ++i)
      if (matchOnRight[i] != -1)
	matching.emplace_back(i, matchOnRight[i]);
  }
public:
  Solver() {
    freopen("cuplaj.in", "r", stdin);
    freopen("cuplaj.out", "w", stdout);
  }
  ~Solver() {
    fclose(stdin);
    fclose(stdout);
  }
  void execute() {
    int L, R, M;
    scanf("%d%d%d", &L, &R, &M);
    vector<vector<int>> left(L), right(R);
    int fromLeft, toRight;
    
    for (int i = 0; i < M; ++i) {
      scanf("%d%d", &fromLeft, &toRight);
      --fromLeft; --toRight;
      left[fromLeft].emplace_back(toRight);
      right[toRight].emplace_back(fromLeft);
    }

    vector<tuple<int,int>> matching;
    hopcroftKarp(left, right, matching);
    printf("%d\n", (int)matching.size());
    for (auto [from, to]: matching)
      printf("%d %d\n", from + 1, to + 1);
  }
};

int main()
{
  unique_ptr<Solver> s = make_unique<Solver>();
  s->execute();
  return 0;
}