Cod sursa(job #2425129)

Utilizator theodor.moroianuTheodor Moroianu theodor.moroianu Data 24 mai 2019 13:09:52
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.1 kb
#include <bits/stdc++.h>
using namespace std;

struct Dinic {
	struct Edge {
		int to, flow, next;
	};
	vector <Edge> edges;
	vector <int> head, act, h;
	int S, D;

	void AddEdge(int from, int to, int f) {
		edges.push_back({ to, f, (int)edges.size() });
		swap(edges.back().next, head[from]);
		edges.push_back({ from, 0, (int)edges.size() });
		swap(edges.back().next, head[to]);
	}

	bool bfs() {
		fill(h.begin(), h.end(), -1);
		h[S] = 0;
		vector <int> q = { S };
		for (int it = 0; it < q.size() && h[D] == -1; it++) {
			int nod = q[it];
			for (int i = head[nod]; i != -1; i = edges[i].next)
				if (edges[i].flow && h[edges[i].to] == -1)
					h[edges[i].to] = 1 + h[nod], q.push_back(edges[i].to);
		}
		return h[D] != -1;
	}

	int dfs(int nod, int flow) {
		if (flow == 0 || nod == D)
			return flow;
		int ans = 0;
		while (act[nod] != -1 && flow) {
			Edge& e = edges[act[nod]];
			int d;
			if (e.flow && h[e.to] == 1 + h[nod] && (d = dfs(e.to, min(flow, e.flow))) != 0) {
				e.flow -= d;
				edges[act[nod] ^ 1].flow += d;
				ans += d;
				flow -= d;
			}
			else
				act[nod] = edges[act[nod]].next;
		}
		return ans;
	}

	int GetFlow() {
		int f = 0;
		while (bfs()) {
			act = head;
			int d;
			while ((d = dfs(S, 1e9)) != 0)
				f += d;
		}
		return f;
	}

	Dinic(int dim = 0, int s = 0, int d = 0) : head(dim + 1, -1), h(dim + 1), S(s), D(d) { }
} flow;

int main()
{
	FILE* in = fopen("cuplaj.in", "r");
	FILE* out = fopen("cuplaj.out", "w");

	int n, m, e;
	fscanf(in, "%d%d%d", &n, &m, &e);

	flow = Dinic(n + m + 1, 0, n + m + 1);

	for (int i = 1; i <= n; i++)
		flow.AddEdge(0, i, 1);
	for (int i = 1; i <= m; i++)
		flow.AddEdge(n + i, n + m + 1, 1);

	while (e--) {
		int a, b;
		fscanf(in, "%d%d", &a, &b);
		b += n;
		flow.AddEdge(a, b, 1);
	}

	int ans = flow.GetFlow();
	fprintf(out, "%d\n", ans);

	for (int nod = 1; nod <= n; nod++)
		for (int i = flow.head[nod]; i != -1; i = flow.edges[i].next)
			if (flow.edges[i].to > n && flow.edges[i].flow == 0)
				fprintf(out, "%d %d\n", nod, flow.edges[i].to - n);
	
	return 0;
}