Cod sursa(job #2962386)

Utilizator AntoniaPopoviciAntonia-Adelina Popovici AntoniaPopovici Data 8 ianuarie 2023 15:01:51
Problema Cuplaj maxim in graf bipartit Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.21 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
const int N = 1 << 14;

/*
cuplaj maxim = submultime de muchii M astfel incat pentru toate varfurile v din V, există cel mult o muchie în M incidentă în v este un subset de muchii
graful este stocat in doi vectori (stanga si dreapta), fiecare reprezentand cate o partitie

Algoritmul cauta o distanta din partitia din stanga, merge prin muchii, ajunge la partitia din dreapta
(noduri din fiecare partitie)
se repeta pana nu mai gaseste distante

cupleaza(int x)
- x (din stanga)
- incearca sa gaseasca un drum incepand de la x
- incearca sa potriveasca cu fiecare nod din dreapta un nod "unmatched" din stanga
- dacă gaseste => true; dacă nu => apelează recursiv nodul care se potrivește în prezent cu nodul din dreapta si returnează rezultatul


cuplaj()
- se apeleaza recursiv pentru fiecare nod nepotrivit din partiția din stânga până când nu mai pot fi găsite drumuri Numărul de muchii din cuplarea maximă este stocat în variabila c,
- nodurile ok sunt pastrate in dr si st
*/

// COMPLEXITATE TIMP: O(n*m)
int c, n, m, st[N], dr[N];
vector<int> stanga[N], dreapta[N];
bool viz[N];

void citire()
{
	int e, x, y;
	fin >> n >> m >> e;
	while (e--)
	{
		fin >> x >> y;
		dreapta[x].push_back(y);
		stanga[y].push_back(x);
	}
}

bool cupleaza(int x)
{
	int y;
	if (viz[x])
		return false;
	viz[x] = true;
	for (size_t i = 0; i < dreapta[x].size(); ++i)
	{
		y = dreapta[x][i];
		if (!st[y])
		{
			dr[x] = y;
			st[y] = x;
			return true;
		}
	}
	for (size_t i = 0; i < dreapta[x].size(); ++i)
	{
		y = dreapta[x][i];
		if (cupleaza(st[y]))
		{
			dr[x] = y;
			st[y] = x;
			return true;
		}
	}
	return false;
}

void cuplaj()
{
	int i;
	bool gata;
	do {
		gata = true;
		memset(viz, 0, sizeof(viz));
		for (i = 1; i <= n; ++i)
			if (!dr[i])
			{
				cupleaza(i);
				if (dr[i])
				{
					++c;
					gata = false;
				}
			}
	} while (!gata);
}

void scrie()
{
	fout << c << '\n';
	for (int i = 1; i <= n; ++i)
		if (dr[i])
			fout << i << " " << dr[i] << '\n';
}

int main()
{
	citire();
	cuplaj();
	scrie();
	return 0;
}