Cod sursa(job #2085993)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 10 decembrie 2017 23:14:12
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.29 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <cstring>

#define NMax 10010

using namespace std;

vector<int> G[NMax];
int leftCardinal, rightCardinal, edgesCardinal;
int L[NMax], R[NMax];
bool viz[NMax];

bool HopcroftKarp(const int &leftNode)
{
	if (viz[leftNode])
	{
		return false;
	}
	viz[leftNode] = true;
	for (vector<int>::iterator it = G[leftNode].begin(); it != G[leftNode].end(); ++it) // *it este un vecin de-al lui leftNode din dreapta lui
	{
		if (L[*it] == 0) // daca am gasit un vecin *it din dreapta lui leftNode care nu e cuplat cu nimeni din stanga atunci cuplam leftNode cu *it
		{
			R[leftNode] = *it;
			L[*it] = leftNode;
			return true; // returnam true pentru ca am putut imbunatati cuplajul folosind un lant alternant, format din muchia de la leftNode la *it
		}
	}
	// daca am ajuns aici inseamna ca toti vecinii din dreatpa lui leftNode sunt cuplati cu cineva din stanga si vom incerca sa gasim un lant alternant
	// trecand prin aceste noduri
	for (vector<int>::iterator it = G[leftNode].begin(); it != G[leftNode].end(); ++it)
	{
		if (HopcroftKarp(L[*it])) 
		{
			// daca am reusit sa cuplam nodul L[*it], care era candva cuplat cu *it atunci inseamna ca *it a ramas liber si il putem cupla cu leftNode
			R[leftNode] = *it;
			L[*it] = leftNode;
			return true;
		}
	}
	return false;
}

int main()
{
	ifstream f("cuplaj.in");
	f >> leftCardinal >> rightCardinal >> edgesCardinal;
	for (int i = 1; i <= edgesCardinal; ++i)
	{
		int x, y;
		f >> x >> y;
		G[x].push_back(y); // x este un nod din stanga, iar G[x] este lista cu toti vecinii din dreapta
	}
	f.close();

	bool done = false;
	while (!done)
	{
		done = true;
		memset(viz, 0, sizeof(viz));
		for (int i = 1; i <= leftCardinal; ++i)
		{
			if (R[i] == 0)
			{
				if (HopcroftKarp(i)) // daca am imbunatit cuplajul folosind un lant alternant care incepe din nodul i din partea stanga
				{
					done = false;
				}
			}
		}
	}

	ofstream g("cuplaj.out");
	int matchingCardinal = 0;
	for (int i = 1; i <= leftCardinal; ++i)
	{
		if (R[i] != 0)
		{
			++matchingCardinal;
		}
	}
	g << matchingCardinal << "\n";
	for (int i = 1; i <= leftCardinal; ++i)
	{
		if (R[i] != 0)
		{
			g << i << " " << R[i] << "\n";
		}
	}
	
	g.close();
	return 0;
}