Pagini recente » Cod sursa (job #2663442) | Cod sursa (job #1923035) | Cod sursa (job #3122815) | Cod sursa (job #1281602) | Cod sursa (job #806825)
Cod sursa(job #806825)
// Cuplaj in graf bipartit cu liste alternante
// Solutia este un greedy care cupleaza un nod cu
// primul necuplat din cealalta multime si in cazul
// in care nu avem cu cine sa cuplam nodul actual
// vom incerca sa decuplam pe rand fiecare pereche din
// cealalta parte. Deci vom cauta pe rand la fiecare nod
// Toate posibilitatile de emergenta de mai sus , astfel
// vom avea de parcurs cel mult L muchii , deci L pasi
// pentru fiecare N muchii. Deci O(N*L) supraestimat.
// O alta abordarea a cuplajului maxim este tratarea acestuia
// ca o retea cu flux si folosirea algoritmilor de flux maxim.
// O rezolvare cu retinerea arborelui BFS cu parinti si cu
// parcurgerea unui numar maxim de drumuri la un pas aduce o
// complexitate de flux in retea. Comeplexitate daca implementam
// dupa cele de mai sus este O(N*sqrt(V)) , numarul de pasi fiind
// maxim sqrt(V) , acesta numindu-se algritmul lui Hopcroft Karp.
// Reteaua de flux va porni din nodul s care va avea muschii la
// fiecare nod din prima multime si se va termina la nodul t care
// va fi legat la fiecare nod din a 2-a multime.
// Metoda 1 in sine merge pe un drum in sus de lungime cel mult L.
// Deci la fiecare pas incerc sa cuplez nodul actual cu unul nou ,
// iar daca nu reusesc incerc sa recuplez fiecare nod de mai sus
// cu altul decat cel acutal. Daca nici un nod de mai sus nu are gradul
// mai mare ca 0 cuplajul ramane acelasi. In caz contrar se schimba.
// Datorita faptului ca legaturile sunt deja notate in L si R nici un
// nod nu va schimba legaturile decat daca poate. Daca poate sa schimbe
// un nod legaturile le vor schimba si restul nodruilor din parcurgere.
#include <fstream>
#include <vector>
#include <cstring>
using namespace std;
ifstream F("cuplaj.in");
ofstream G("cuplaj.out");
const int Nmax = 10010;
vector<int> A[Nmax];
int Fixed[Nmax];
int L[Nmax],R[Nmax];
int N,M,T,Sol;
typedef vector<int>::iterator IT;
int Look( int Nod )
{
if ( Fixed[Nod] == 1 ) return 0; // deca legatura e fixata iesim
Fixed[Nod] = 1; // fixam nodul
for (IT it=A[Nod].begin();it!=A[Nod].end();++it)
// ma uit daca vreun nod direct e necuplat
if ( R[*it] == 0 )
{
L[ Nod ] = *it;
R[ *it ] = Nod;
return 1;
}
for (IT it=A[Nod].begin();it!=A[Nod].end();++it)
// daca nu a fost nici un nod necuplat ma uit la un posibil cuplaj anterior
if ( Look( R[*it] ) )
{
L[ Nod ] = *it;
R[ *it ] = Nod;
return 1;
}
return 0; // asta se intampla daca nu am reusit sa facem nici o legatura
}
int main()
{
F>>N>>M>>T;
for (int i=1,x,y;i<=T;++i)
{
F>>x>>y;
A[x].push_back(y);
}
for (int i=1;i<=N;++i)
if ( L[i] == 0 ) // daca nodul actual nu e cuplat il cuplez
{
if ( !Look(i) ) // daca nu pot sa il cuplez
{
memset(Fixed, 0, sizeof(Fixed)); // nici o legatura anterioara nu e fixata
// in cel mai rau caz voi ramane la numarul actual de legaturi , o legatura
// veche fiind inlocuita cu aceasta noua
Sol += Look(i);
}
else
++Sol;
}
G<<Sol<<'\n';
for (int i=1;i<=N;++i)
if ( L[i] )
G<<i<<' '<<L[i]<<'\n';
}