Cod sursa(job #2179093)

Utilizator Dddarius95Darius-Florentin Neatu Dddarius95 Data 19 martie 2018 22:33:02
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.72 kb
// cuplaj - O(sqrt(n) * m)
#include <iostream>
#include <cstdio>
#include <fstream>
#include <vector>
#include <bitset>
#include <cassert>
#include <cstring>
#include <algorithm>
#define NMAX 10009
using namespace std;

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

int n, m, e, sol;
int dr[NMAX]; // dr[i] = pentru nodul i din stanga, cine este perechea lui din dreapta
int st[NMAX]; // st[i] = pentru nodul i din dreapta, cine este perechea lui din stanga

vector<int> G[NMAX];
bitset<NMAX> viz;

void read_input() {
    f >> n >> m >> e;

    for (int i = 1; i <= e; ++i) {
          int x, y;
          f >>  x >> y;

          G[x].push_back(y);
    }
}

int cupleaza(int node) {
     // daca nodul node din STANGA este vizitat
     if (viz[node]) {
        return 0;  // nu il pot cupla
     }

     viz[node] = 1; // l-am vizitat

     // incerc sa il cuplez pe node cu un nod din stanga NECUPLAT
     for (auto it : G[node]) { // it e nod in dreapta
          if (!st[it]) {
               dr[node] = it;
               st[it] = node;
               return 1;       // am reusit sa cuplez fara sa schimb ceva cuplat deja
          }
     }

     // vedem daca putem sa recuplam alte noduri fara sa micsoram solutia si sa il cuplam si pe node
     for (auto it : G[node]) {               // it este nod in dreapta
          // st[it] != 0: it din dreapta este cuplat cu st[it] din stanga
          // cupleaza(st[it]) incearca sa il recupleze pe st[it], fara sa  miscoreze solutia
          if (st[it] != 0 && cupleaza(st[it])) {
               dr[node] = it;
               st[it] = node;
               return 1;      // am reusit sa schimb perechea lui st[it] (dr[ st[it] ] = altceva)
          }
     }

     return 0; // altfel nu se poate cupla fara sa micsoram solutia
}

void cuplaj() {
     sol = 0; // cate muchii am in cuplaj

     bool ready = false;
     while (!ready) {
          ready = true;    // presupun ca sunt gata
          for (int i = 1; i <= n; ++i) {
               viz[i] = 0; // resetez pt revizitare
          }

          // parcurg fiecare nod din STANGA
          for (int i = 1; i <= n; ++i) {
               // daca nodul i din stanga nu e cuplat: dr[i] == 0
               // si se poate cuplaL cupleaza(i) != 0
               if (!dr[i] && cupleaza(i)) {
                    sol++;         // am crescut solutia
                    ready = false; // am presupus prost, nu am terminat
               }
          }
     }

     g << sol << "\n";
     for (int i = 1; i <= n; ++i) {
          if (dr[i] != 0) {
               g << i << " " << dr[i] << "\n";
          }
     }
}

int main() {
    read_input();
    cuplaj();
    return 0;
}