Pagini recente » Cod sursa (job #61474) | Cod sursa (job #845166) | Cod sursa (job #2494995) | Cod sursa (job #882171) | Cod sursa (job #2960127)
/*
Ideea de rezolvare a algoritmului este urmatoarea:
Folosim algoritmul de Max Flow. In plus, folosim optimizarea mentionata pe infoarena: La fiecare pas construim arborele BFS (excluzand destinatia),
si acum un drum de la sursa la destinatie e reprezentat de un drum de la sursa (care este radacina arborelui) la o frunza legata de destinatie printr-o
muchie nesaturata. Astfel putem la un pas sa marim fluxul pe un numar maximal de astfel de drumuri, fara a mai reface BFS-ul. Aceasta optimizare
reduce destul de mult timpul de executie.
Acum vine partea de cuplaj:
Complexitate:
Fie n = numarul de noduri, m = numarul de muchii
Timp: O(n*m^2) ///totusi, avem optimizarea cu arborele BFS
Memorie: O(n^2) ///matrice de adiacenta. Asta totusi ne aduce un timp mai bun. Fiindca avem putine noduri, maxim 1000, e chiar mai sanatos asa
*/
#include <bits/stdc++.h>
using namespace std;
ifstream f("cuplaj.in");
ofstream g("cuplaj.out");
int n,m,s,t;
int viz[10005];
int parinte[10005];
int graf[10005][10005];
long long flux_maxim;
void AddMuchie(int x, int y, int c)
{
graf[x][y]=c;
}
bool bfs()
{
memset(viz,0,sizeof(viz));
memset(parinte,0,sizeof(parinte));
queue <int> q;
viz[0]=1;
q.push(0);
while(!q.empty())
{
int act=q.front();
q.pop();
if(act==t) ///am ajuns la nodul t, deci exista un drum de la s la t pe care nu l-am saturat
return true;
for(int i=0;i<n;i++) ///ne uitam prin vecinii nodului actual
if(viz[i]==0 && graf[act][i]>0) ///nodul nu e vizitat, iar muchia (fie ea din graful rezidual sau nu) mai accepta flux
{
viz[i]=1;
parinte[i]=act;
q.push(i);
}
}
return false;
}
int maxFlow()
{
while(bfs()) ///cat timp mai exista drumuri nesaturate de la s la t
{
for(int i=0;i<n-1;i++)
{ if(viz[i]!=0 && graf[i][t]>0)
{
int aux_flux=1<<30; ///facem asta ca sa luam minimul de pe drum
parinte[t]=i;
int j=t;
while(parinte[j]!=0) ///calatorim din tata in tata pana ajungem la s si vedem cat flux putem baga pe drumul ala (bottleneck inclus)
{
aux_flux=min(aux_flux,graf[parinte[j]][j]);
j=parinte[j];
}
if(aux_flux!=0) ///Putem adauga flux pe drum
{
int j=t;
while(parinte[j]!=0) ///mergem din tata in tata si modificam muchiile pe graful normal + cel rezidual
{
graf[parinte[j]][j]-=aux_flux;
graf[j][parinte[j]]+=aux_flux;
j=parinte[j];
}
flux_maxim=flux_maxim+aux_flux; ///adaugam la flux_maxim fluxul pe care il avem pe drumul calculat
}
}
}
}
return flux_maxim;
}
int main()
{
int grup1,grup2;
f>>grup1>>grup2>>m;
n=grup1+grup2+2;
s=0;
t=n-1;
int x,y,c;
for(int i=1;i<=m;i++)
{
f>>x>>y;
AddMuchie(x,y+grup1,1);
}
for(int i=1;i<=grup1;i++)
AddMuchie(s,i,1);
for(int i=grup1+1;i<=grup1+grup2;i++)
AddMuchie(i,t,1);
m=m+grup1+grup2;
g<<maxFlow()<<'\n';
return 0;
}