Cod sursa(job #2960127)

Utilizator Nicolae11Mihaila Nicolae Nicolae11 Data 3 ianuarie 2023 16:38:18
Problema Cuplaj maxim in graf bipartit Scor 8
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.38 kb
/*
    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;
}