Cod sursa(job #460549)

Utilizator unholyfrozenCostea Andrei unholyfrozen Data 3 iunie 2010 06:20:05
Problema Cuplaj maxim in graf bipartit Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 2.77 kb
#include<cstdio>
#include<vector>
#include<queue>

using namespace std;

const int NMAX = 20000;
int Q[NMAX];

class graf
{
	int A, B;
	int M;
	int* V[NMAX];
	int nr[NMAX];
	int la[NMAX];
	bool cauta_lantalternant(int x, int* cuplat, int *seen, int *prev);	
public:
	graf(int A, int B, int M);
	~graf();
	void punemuchie(int a, int b);
	void add(int a, int b);
	void aloca();
	vector<int> hopcroftkarp();
};

int main()
{
	int A, B, M;

	freopen("cuplaj.in", "r", stdin);
	freopen("cuplaj.out", "w", stdout);

	scanf("%d %d %d", &A, &B, &M);
	graf G(A, B, M);
	for(;M--;)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		a--, b--;
		G.add(a, b);
	}
	G.aloca();
	rewind(stdin);

	scanf("%d %d %d", &A, &B, &M);
	for(;M--;)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		a--, b--;
		G.punemuchie(a, b);
	}

	vector<int> sol;
	sol = G.hopcroftkarp();
	printf("%d\n", sol[0]);
	for(int i = 1; i < A + 1; i++)
	{
		if(sol[i] != -1)
		printf("%d %d\n", i, sol[i] + 1 - A);
	}
	return 0;
}

graf::graf(int A, int B, int M)
{
	this->A = A;
	this->B = B;
	this->M = M;	
	for(int i = 0; i < A + B; i++)
		nr[i] = 0, la[i] = 0;
}
graf::~graf()
{
	for(int i = 0; i < A + B; i++)
		delete V[i];
}

void graf::punemuchie(int a, int b)
{
	V[a][la[a]++] = A + b;
	V[A + b][la[A + b]++] = a;
}

vector<int> graf::hopcroftkarp()
{
	int *seen;
	seen = new int[A + B];
	int *cuplat;
	cuplat = new int[A + B];
	int *prev;
	prev = new int[A + B];

	for(int i = 0 ; i < A + B; i++)
		cuplat[i] = -1;

	while(1)
	{
		bool ok = false;
		for(int i = 0; i < A + B; i++)
			seen[i] = 0;
		for(int i = 0; i < A; i++)
			if(cuplat[i] == -1)
			{
				 ok |= cauta_lantalternant(i, cuplat, seen, prev);
			}
		if(!ok) break;
	}

	vector<int> sol;
	sol.push_back(0);
	for(int i = 0; i < A; i++)
		{
			sol.push_back(cuplat[i]);
			if(cuplat[i] != -1)
			sol[0]++;
		}
	delete seen;
	delete cuplat;
	delete prev;
	return sol;
}

bool graf::cauta_lantalternant(int x, int* cuplat, int *seen, int *prev)
{
	int b = 0, e = 0;
	Q[b] = x;
	seen[x] = 1;
	prev[x] = -1;
	int ok = 0;
	while(b <= e)
	{
		x = Q[b++];
		if(!ok)
		{
		for(int i = 0; i < nr[x]; i++)
			if(!seen[V[x][i]])
			{
				Q[++e] = V[x][i];
				prev[V[x][i]] = x;
				seen[V[x][i]] = 1;
				if(cuplat[V[x][i]] == -1)
				{
					for(int j = V[x][i]; j != -1;)
					{
						int y;
						cuplat[j] = prev[j];
						y = cuplat[prev[j]];
						cuplat[prev[j]] = j;
						j = y;
					}
					return true;
				}
			}
		}
		else
		{
			if(!seen[cuplat[x]])
			Q[++e] = cuplat[x];
		}
		ok = !ok;
	}
	return false;
}

void graf::add(int a, int b)
{
	nr[a]++;
	nr[A + b]++;
}

void graf::aloca()
{
	for(int i = 0; i < A + B; i++)
		V[i] = new int[nr[i]];
}