Cod sursa(job #1462075)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 17 iulie 2015 00:31:30
Problema Cuplaj maxim in graf bipartit Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.15 kb
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <vector>
#include <list>
#include <queue>
#include <cstdlib>
#include <cstring>
using namespace std;
#define _submit
#ifdef _submit
#define InFile "cuplaj.in"
#define OtFile "cuplaj.out"
#else
#define InFile "fis.in"
#define OtFile "fis.out"
#endif

class edge {
private:
	int toNod, capacity, *flow;
	edge(int N, int p, int* f) {
		toNod = N;
		capacity = p;
		flow = f;
	}
	friend class graph;
};

class graph {
private:
	vector< list<edge> > adiac;
public:
	graph(int N) { adiac.resize(N + 1); }
	void addEdge(int n1, int n2, int cap) {
		int* f = new int(0);
		adiac[n1].push_back(edge(n2, cap, f));
		adiac[n2].push_back(edge(-n1, cap, f));
	}
	int size() { return adiac.size() - 1; }
	bool getAugmentingPath(int nod, int endNod, vector<char>& visited, vector<int*>& pathFlows, int& minFlow) {
		visited[nod] = 1;
		if (nod == endNod)
			return true;
		for (auto i = adiac[nod].begin(); i != adiac[nod].end(); ++i) {
			int neigh = i->toNod > 0 ? i->toNod : -i->toNod;
			if (visited[neigh])
				continue;
			bool isForwardArc = i->toNod > 0 ? true : false;
			bool isAvailable = false;
			if (isForwardArc && *(i->flow) < i->capacity) {
				isAvailable = true;
				if (i->capacity - *(i->flow) < minFlow)
					minFlow = i->capacity - *(i->flow);
			}
			else if (!isForwardArc && *(i->flow) > 0) {
				isAvailable = true;
				if (*(i->flow) < minFlow)
					minFlow = *(i->flow);
				*(i->flow) = -(*(i->flow));
			}
			if (isAvailable) {
				if (getAugmentingPath(neigh, endNod, visited, pathFlows, minFlow)) {
					pathFlows.push_back(i->flow);
					return true;
				}
			}
		}
		return false;
	}
#define MAXEDGES 11000
#define INFINIT 100000
	int FordFulkerson(int source, int sink) {
		int s = 0;
		vector<int*> pathFlows;
		pathFlows.reserve(MAXEDGES);
		vector<char> visited(size() + 1);
		while (true) {
			int minFlow = INFINIT;
			visited.assign(size() + 1, 0);
			pathFlows.clear();
			getAugmentingPath(source, sink, visited, pathFlows, minFlow);
			if (!pathFlows.size())
				break;
			s += minFlow;
			for (auto i = pathFlows.begin(); i != pathFlows.end(); ++i) {
				if (**i < 0) {
					**i = -(**i);
					**i -= minFlow;
				}
				else
					**i += minFlow;
			}
		}
		return s;
	}
	void printBipartiteFlow(int source, int sink, int offset1, int offset2) {
		for (int i = 1; i < size() + 1; i++) {
			if (i != source)
			for (auto j = adiac[i].begin(); j != adiac[i].end(); ++j)
			if (j->toNod > 0 && j->toNod != sink && *j->flow != 0)
				printf("%d %d\n", i - offset1, j->toNod - offset2);
		}
	}
};

int main() {
	assert(freopen(InFile, "r", stdin));
	assert(freopen(OtFile, "w", stdout));
	int N, M, E;
	scanf("%d%d%d", &N, &M, &E);
	graph* G = new graph(N + M + 2);
	for (int i = 0; i < E; i++) {
		int a, b;
		scanf("%d%d", &a, &b);
		G->addEdge(a + 1, b + N + 1, 1);
	}
	for (int i = 2; i <= N + 1; i++)
		G->addEdge(1, i, 1);
	for (int i = N + 2; i <= N + M + 1; i++)
		G->addEdge(i, N + M + 2, 1);
	printf("%d\n", G->FordFulkerson(1, N + M + 2));
	G->printBipartiteFlow(1, N + M + 2, 1, N + 1);
	return 0;
}