Cod sursa(job #877957)

Utilizator vendettaSalajan Razvan vendetta Data 13 februarie 2013 16:24:23
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.44 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>

using namespace std;

ifstream f("cuplaj.in");
ofstream g("cuplaj.out");

#define nmax 10005
#define ll long long

int n, m, st[nmax], dr[nmax], e;
bool viz[nmax];
vector<int> gf[nmax];

void citeste(){
    f >> n >> m >> e;
    int x, y;
    for(int i=1; i<=e; ++i){
        f >> x >> y;
        gf[x].push_back(y);
    }
}

inline bool cupleaza(int nod){
    if (viz[nod] != 0) return 0;
    viz[nod] = 1;
    // incerc sa il cuplez cu un vecin
    for(int i=0; i<gf[nod].size(); ++i){
        int vc = gf[nod][i];
        if ( dr[vc] == 0 ){// i-am gasit perechea:>
            st[nod] = vc;
            dr[vc] = nod;
            return 1;
        }
    }

    // acum incerc sa-l cuplez pe nod cu un vecin cu conditia ca : fie X nodul din partea stanga cu care s-a cuplat vecinul;
    // pe nod il cuplez cu vecin doar daca nodul X il pot recupla cu un alt nod
    for(int i=0; i<gf[nod].size(); ++i){
        int vc = gf[nod][i];
        if ( cupleaza(dr[vc]) ){//daca am reusit sa il cuplez cu un alt nod diferit de vc
            // atunci pe nod il pot cupla cu vc
            st[nod] = vc;
            dr[vc] = nod;
            return 1;
        }
    }
    return 0;
}

void rezolva(){
    // in primul rand algoritmul se foloseste de proprietatea ca daca la un momendat un nod x e cuplat atunci e cel mult va fi recuplat
    // si acest lucru nu strica cu nimic realizarea cuplajului maxim
    // ideea ar fi ca incerc sa cuplez fiecare nod; daca toti vecinii lui nod sunt cuplati atunci incerc sa cuplez un vecin de al lui nod
    // cu un alt nod si astfel pe nod il pot cupla cu acel vecin
    // + mai tin un st[i] = j; i face partea din multimea din stanga iar j e din multimea din dreapta (adica pe i il cuplez cu j)
    // dr[i] = invers
    int cnt = 0;
    for(int ok=1; ok; ){
        ok = 0;
        for(int i=1; i<=n; ++i) viz[i] = 0;
        for(int i=1; i<=n; ++i){
            if (st[i] == 0 && cupleaza(i) > 0 ){
                ok = 1; ++cnt;
            }
        }
    }

    //cout << cnt << "\n";
    g << cnt << "\n";
    for(int i=1; i<=n; ++i){
        if (st[i] != 0){
            g << i << " " << st[i] << "\n";
            //cout << i << " " << st[i] << "\n";
        }
    }
}

int main(){
    citeste();
    rezolva();

    f.close();
    g.close();

    return 0;
}