Cod sursa(job #1953711)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 4 aprilie 2017 23:07:25
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.68 kb
#include <cstdio>
#include <climits>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cassert>
#include <queue>
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
typedef long long LL;

#define MAXN 20010
typedef vector< vector<int> > graph;
graph G;
int N, L, R, E;

struct edge {
	int u, C;
	edge(int uu, int cc) : u(uu), C(cc) {}
};
vector<edge> edges;

inline void addEdge(int v, int u, int c) {
	G[v].push_back((int)edges.size());
	edges.push_back(edge(u, c));
	G[u].push_back((int)edges.size());
	edges.push_back(edge(v, 0));
}

int nedge[MAXN], dst[MAXN], Q[MAXN];
int _;
int ql, qr;
#define INFINIT 0x3F3F3F3F

bool BFS(int s) {
	memset(dst, 0x3F, sizeof(dst));
	dst[s] = 0;
	ql = 0, qr = 1;
	while ((ql < qr) && (dst[N - 1] == INFINIT)) {
		int t = Q[ql++];
		for (int i = 0; i != (int)G[t].size(); ++i) {
			int edgeID = G[t][i];
			int u = edges[edgeID].u;
			if (!edges[edgeID].C) continue;
			if (dst[u] != INFINIT) continue;
			dst[u] = dst[t] + 1;
			Q[qr++] = u;
		}
	}
	return (dst[N - 1] != INFINIT);
}

int DFS(int v, int flow) {
	if (v == (N - 1)) return flow;
	for (; nedge[v] != (int)G[v].size(); ++nedge[v]) {
		int edgeID = G[v][nedge[v]];
		int u = edges[edgeID].u;
		if (!edges[edgeID].C) continue;
		if (dst[v] + 1 != dst[u]) continue;
		int actualFlow = DFS(u, min(edges[edgeID].C, flow));
		if (actualFlow == 0) continue;
		edges[edgeID].C -= actualFlow;
		edges[edgeID ^ 1].C += actualFlow;
		return actualFlow;
	}
	return 0;
}

int blockingFlow() {
	int totalFlow = 0;
	memset(nedge, 0, sizeof(nedge));
	int flow = 0;
	while ((flow = DFS(0, INFINIT))) totalFlow += flow;
	return totalFlow;
}

int Dinic() {
	int flow = 0;
	while (BFS(0)) flow += blockingFlow();
	return flow;
}

void input() {
	_ = scanf("%d%d%d", &L, &R, &E);
	N = L + R + 2;
	G.resize(N);
	for (int i = 0; i < E; ++i) {
		int a, b;
		_ = scanf("%d%d", &a, &b);
		b += L;
		addEdge(a, b, 1);
	}
	for (int i = 1; i <= L; ++i)
		addEdge(0, i, 1);
	for (int j = 0; j < R; ++j)
		addEdge(j + L + 1, N - 1, 1);
}

void printMatching() {
	for (int i = 1; i <= L; ++i)
	for (int j = 0; j != (int)G[i].size(); ++j)
	if (edges[G[i][j] ^ 1].C && edges[G[i][j]].u) {
		printf("%d %d\n", i, edges[G[i][j]].u - L);
		break;
	}
}

int main() {
	_ = (int)freopen(InFile, "r", stdin);
	_ = (int)freopen(OuFile, "w", stdout);
	input();
	printf("%d\n", Dinic());
	printMatching();
	return 0;
}