Cod sursa(job #2247771)

Utilizator cosmin.pascaruPascaru Cosmin cosmin.pascaru Data 29 septembrie 2018 01:33:07
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.06 kb
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <array>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <assert.h>
#include <queue>
#include <chrono>
#include <memory>
 
using LL = long long;
using ULL = int long long;
 
const std::string _problemName = "cuplaj";
 
namespace std {
std::ifstream fin(_problemName + ".in");
std::ofstream fout(_problemName + ".out");
}
 
#define USE_FILES
 
#ifdef USE_FILES
#define cin fin
#define cout fout
#endif

using graph_t = std::vector< std::vector<int> >; 

int n, m, e;

graph_t edgesFromLeft;

std::vector<int> matchesFromLeft;
std::vector<int> matchesFromRight;

std::vector<int> leftVisited;

void doMatch(int leftNode, int rightNode) {
    matchesFromLeft [leftNode]  = rightNode;
    matchesFromRight[rightNode] = leftNode ;
}

bool doImproveSimple(int leftNode) {
    for (int rightNode : edgesFromLeft[leftNode]) {
        if (matchesFromRight[rightNode] == -1) {
            doMatch(leftNode, rightNode);
            return true;
        }
    }
    return false;
}

bool doImprove(int leftNode);

bool doImproveWithReassign(int leftNode) {
    for (int rightNode : edgesFromLeft[leftNode]) {
        // assert matchesFromRight[rightNode] != -1
        if (doImprove(matchesFromRight[rightNode])) {
            doMatch(leftNode, rightNode);
            return true;
        }
    }
    return false;
}

bool doImprove(int leftNode) {
    if (leftVisited[leftNode]) {
        return false;
    }

    leftVisited[leftNode] = true;

    bool improved = false;
    
    improved = improved || doImproveSimple(leftNode);
    improved = improved || doImproveWithReassign(leftNode);

    return improved;
}

bool doImprove() {
    bool improved = false;

    std::fill(leftVisited.begin(), leftVisited.end(), false);

    for (int leftNode = 0; leftNode < n; ++leftNode) {
        if (matchesFromLeft[leftNode] == -1) {
            improved = improved | doImprove(leftNode);
        }
    }

    return improved;
}

int main() {
    std::cin >> n >> m >> e;
 
    edgesFromLeft.resize(n);
    matchesFromLeft.resize(n);
    matchesFromRight.resize(m);

    std::fill(matchesFromLeft.begin(), matchesFromLeft.end(), -1);
    std::fill(matchesFromRight.begin(), matchesFromRight.end(), -1);

    leftVisited.resize(n);

    while (e--) {
        int x, y;
        std::cin >> x >> y;

        --x, --y;
        edgesFromLeft[x].push_back(y);
    }

    bool improved;
    do {
        improved = doImprove();
    } while (improved);

    std::vector< std::pair<int, int> > matching;
    for (int leftIdx = 0; leftIdx < matchesFromLeft.size(); ++leftIdx) {
        int rightNode = matchesFromLeft[leftIdx];

        if (rightNode != -1) {
            matching.emplace_back(leftIdx, rightNode);
        }
    }

    std::cout << matching.size() << '\n';

    for (auto pair : matching) {
        std::cout << pair.first + 1 << ' ' << pair.second + 1 << '\n';
    }

    return 0;
}