Cod sursa(job #1803833)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 11 noiembrie 2016 22:19:02
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.01 kb
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <list>
#include <queue>
#include <cstring>
#include <set>
#include <cctype>
#include <vector>
using namespace std;

#ifdef INFOARENA
#define ProblemName "cuplaj"
#endif

#define MCONCAT(A, B) A B
#ifdef ProblemName
#define InFile MCONCAT(ProblemName, ".in")
#define OuFile MCONCAT(ProblemName, ".out")
#else
#define InFile "fis.in"
#define OuFile "fis.out"
#endif

#define MAXN 10010

vector<int> G[MAXN];
int leftPair[MAXN], rightPair[MAXN];
char viz[MAXN];
int aib[MAXN][MAXN], N;

void aibUpdate(int anr, int poz, int val) {
	++poz;
	int C = 0;
	while (poz <= N) {
		aib[anr][poz] += val;
		while (!(poz & (1 << C))) C++;
		poz += (1 << C);
		C += 1;
	}
}

int aibSearch(int anr) {
	int i, step, val = 1;
	for (step = 1; step < N; step <<= 1);
	for (i = 0; step; step >>= 1) {
		if (i + step <= N) {
			if (val >= aib[anr][i + step]) {
				i += step, val -= aib[anr][i];
				if (!val) return (i - 1);
			}
		}
	}
	return -1;
}

char pairUp(int nod) {
	if (viz[nod])
		return 0;
	viz[nod] = 1;
	for (auto i : G[nod])
	if (rightPair[i] == -1) {
		rightPair[i] = nod;
		leftPair[nod] = i;
		return 1;
	}
	for (auto i : G[nod])
	if (pairUp(rightPair[i])) {
		rightPair[i] = nod;
		leftPair[nod] = i;
		return 1;
	}
	return 0;
}

int main() {
	assert(freopen(InFile, "r", stdin));
	assert(freopen(OuFile, "w", stdout));
	int N, M, E;
	scanf("%d%d%d", &N, &M, &E);
	while (E--) {
		int n1, n2;
		scanf("%d%d", &n1, &n2);
		--n1, --n2;
		G[n1].push_back(n2);
		aibUpdate(n1, n2, 1);
	}
	
	memset(leftPair, 0xFF, sizeof(leftPair));
	memset(rightPair, 0xFF, sizeof(rightPair));
	char found = 1;
	int flow = 0;
	while (found) {
		found = 0;
		memset(viz, 0, sizeof(viz));
		for (int i = 0; i < N; i++)
		if (leftPair[i] == -1 && pairUp(i))
			flow += (found = 1);
	}
	printf("%d\n", flow);
	for (int i = 0; i < N; i++)
	if (leftPair[i] != -1)
		printf("%d %d\n", i + 1, leftPair[i] + 1);
	return 0;
}