Cod sursa(job #418237)

Utilizator laserbeamBalan Catalin laserbeam Data 15 martie 2010 18:07:35
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.75 kb
// Catalin Balan
// Mon Mar 15 17:35:37 EET 2010
// Cuplaj maxim in graf bipartit

#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>

using namespace std;

#define NMAX 10005
#define CHUNK 8192

#define FIN "cuplaj.in"
#define FOUT "cuplaj.out"

char g_buf[CHUNK];
int g_p=CHUNK-1;

inline int get()
{

	int x = 0;
	while (g_buf[g_p] < '0' || g_buf[g_p] > '9')
		if (++g_p == CHUNK) fread(g_buf,1,CHUNK,stdin), g_p=0;

	while (g_buf[g_p] >= '0' && g_buf[g_p] <= '9')
	{
		x = x*10 + g_buf[g_p]-'0';
		if (++g_p == CHUNK) fread(g_buf,1,CHUNK,stdin), g_p=0;
	}
	return x;
}

int n,m;
int Right[NMAX], Left[NMAX], Viz[NMAX];
vector<int> G[NMAX];
// Right[i] - vecinul nodului i; i se afla in multimea din dreapta
// Left[i]  - vecinul nodului i; i se afla in multimea din stanga

int group( int st )
{
	if (Viz[st]) return false;
	Viz[st] = true;
	vector<int>::iterator it;
	for (it = G[st].begin(); it != G[st].end(); ++it)
	{
		if (!Right[*it])
		{
			Left[st] = *it;
			Right[*it] = st;

			return true;
		}
	}

	for (it = G[st].begin(); it != G[st].end(); ++it)
	{
		if (group (Right[*it]) )
		{
			Left[st] = *it;
			Right[*it] = st;
			return true;
		}
	}
	return false;
}

int main(int argv, char ** argc)
{
	freopen(FIN, "r", stdin);
	freopen(FOUT, "w", stdout);

	n = get();
	m = get();

	for ( int nrMuchii = get(); nrMuchii; --nrMuchii)
	{
		int x = get();
		int y = get();
		G[x].push_back(y);
	}

	int goOn = true;
	while (goOn)
	{
		goOn = false;
		memset(Viz, 0, sizeof(Viz));
		for (int i = 1; i <= n; ++i)
			if ( !Left[i] ) goOn |= group( i );
	}
	
	int cate = 0;
	for (int i = 1; i <= n; ++i)
		cate += (Left[i] != 0);

	printf("%d\n", cate);
	for (int i = 1; i <= n; ++i)
		if (Left[i])
		{
			printf("%d %d\n", i, Left[i]);
		}

	return EXIT_SUCCESS;
}