Cod sursa(job #1775175)

Utilizator danielNiculaeDaniel Niculae danielNiculae Data 9 octombrie 2016 23:11:52
Problema Cuplaj maxim in graf bipartit Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.36 kb
#include "fstream"
#include "vector"

using namespace std;

ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");

const int NMAX = 10005;
const int MMAX = 10005;

int N, M, E;
vector<int> graph[NMAX + MMAX];
int coupling = 0;
int couple[NMAX + MMAX];
bool used[MMAX];

struct cpl {
    int node;
    int parent;
    int t;
};

int createChain(int turns, cpl l, cpl r, bool inChain[], vector<cpl> v, int i) {
    int links = turns;
    bool nextIteration = false;
    while(links--) {
        if(inChain[l.node] || inChain[r.node]) {
            return 0;
        }
        inChain[l.node] = true;
        inChain[r.node] = true;
//        fout << "Visited: " << l.node << ", and: " << r.node << "\n";
//        fout << "Father of left: " << v[l.parent].node << "\n";
//        fout << "Grandfather of left: " << v[v[l.parent].parent].node << "\n";
        r = v[l.parent];
        l = v[v[l.parent].parent];
//        fout << "r.node: " << r.node << "\n";
    }

//    fout << "Connected node: " << v[i].node  - N << "\n";
    links = turns;
    l = v[v[i].parent];
    r = v[i];
//    fout << "Left: " << l.node << ", Right: " << r.node - N << "\n";
    while(links--) {
        couple[l.node] = r.node;
        couple[r.node] = l.node;
        r = v[l.parent];
        l = v[v[l.parent].parent];
    }
    used[v[i].node - N] = true;
    return 1;
}

void findChains(int turns) {
//    fout << "Turns: " << turns << "\n";
    bool visited[NMAX + MMAX], inChain[NMAX + MMAX];

    for(int i = 1 ; i <= N + M ; i++) {
        visited[i] = false;
        inChain[i] = false;
    }

    vector<cpl> v;
    for(int node = 1 ; node <= N ; node++) {
        if(!couple[node]) {
            visited[node] = true;
            cpl c = {node, -1, 0};
            v.push_back(c);
        }
    }

    for(int i = 0 ; i < v.size() ; i++) {
        //if the node is on the left or there haven't been enough turns
        if(v[i].node <= N || v[i].t < turns) {
            for(int j = 0 ; j < graph[v[i].node].size() ; j++) {
                int son = graph[v[i].node][j];
                if(!visited[son]) {
                    int turnOfSon = v[i].t;
                    if (son > N) {
                        turnOfSon++;
                    }
                    visited[son] = true;
                    cpl c = {son, i, turnOfSon};
                    v.push_back(c);
                }
            }
        }
    }

//    for(int i = 0 ; i < v.size() ; i++) {
//        fout << "Position: " << i << ", node: " << v[i].node << ", parent: " << v[i].parent << "\n";
//    }

    for(int i = v.size() - 1 ; i ; i--) {
        if(v[i].node <= N) {
            break;
        }
        if(!used[v[i].node - N]) {
            cpl l = v[v[i].parent];
            cpl r = v[i];
//            fout << "Initialising: " << l.node << ", and: " << r.node << "\n";
            coupling += createChain(turns, l, r, inChain, v, i);
        }
    }
}

int main() {

    fin >> N >> M >> E;

    for(int i = 1 ; i <= E ; i++) {
        int x, y;
        fin >> x >> y;
        graph[x].push_back(N + y);
        graph[N + y].push_back(x);
    }

    for(int i = 1 ; i <= min(N, M) ; i++) {
        findChains(i);
        if(coupling == min(N, M)) {
            break;
        }
    }

    fout << coupling << "\n";
    for(int i = 1 ; i <= N ; i++) {
        if(couple[i]) {
            fout << i << " " << (couple[i] - N) << "\n";
        }
    }

    return 0;
}