Cod sursa(job #1603452)

Utilizator TeodorCotetCotet Teodor TeodorCotet Data 17 februarie 2016 15:56:53
Problema Cuplaj maxim in graf bipartit Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 2.27 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <bitset>

using namespace std;

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

const int NMAX = 10000;
const int MMAX = 10000;

int nodesLeft ; int nodesRight;  int m;

vector< vector<int> > g(NMAX + 1, vector<int>(0));

bitset<NMAX + 1> used;

int pairL[NMAX + 1]; int pairR[NMAX + 1]; 

int cuplaj;

void read() {

	fin >> nodesLeft >> nodesRight >> m;
	for(int i = 1; i <= m ; ++i) {

		int x; int y;
		fin >> x >> y;
		g[x].push_back(y);
	}
}

bool pairUp(int node) {

	if(used[node] == true) return false; 

	used[node] = true;

	for(int x : g[node]) 
		if(pairR[x] == 0) { //pot sa.l imperechez cu un vecin de.al lui

			pairL[node] = x;
			pairR[x] = node;
			return true;
		}
	//daca toti vecinii sunt imperecheati, incerc sa decuplex unul, si sa.i cuplez perechea cu altcineva

	for(int x : g[node]) 
		if(pairUp(pairR[x])) { //daca pot sa.i cuplez perechea perechii nodului meu node 

			pairL[node] = x;
			pairR[x] = node;
			return true;
		}

	return false;
}

void solve() {

	for(int i = 1; i <= nodesLeft; ++i)
		if(pairL[i] == 0)  {
			if(pairUp(i))  
				cuplaj++;
			else {
				/*practic incerc sa fac o noua parcurgere doar atunci cand nu mai pot sa gasesc un drum pentru nodul i
				as putea face o noua parcurgere practic la fiecare pas, adica sa dau used.reset()  de fiecare data dar atunci ar merge mai greu
				pentru ca ar incerca sa faca de mai multe ori pairUp pe aceeasi configuratie */
				used.reset(); 
				cuplaj += pairUp(i); 
			}
		}
	/* Practic algoritmul e echivalent cu edmonds Karp, doar ca in loc de BFS face DFS si cand ajunge la dstinatie se opreste,
		insa pastreaza nodurile care au fost vizitate, iar apoi cand aplica DFS pentru alt nod (incerca sa.l cupleze) foloseste
		aceeasi configuratie a nodurilor vizitate si mai adauga altele. L reseteaza doar cand nu mai exitsa drum pentru un nou nod.
		Merge mai repede decat daca se face un DFS nou tot timpul. DFS astea tin cont de mai multe restrictii. */
}

void print() {

	fout << cuplaj << '\n'; 

	for(int i = 1; i <= nodesLeft ; ++i) 
		if(pairL[i])
			fout << i << " " << pairL[i] << '\n'; 
}

int main() {

	read();

	solve();

	print();

	return 0;
}