Cod sursa(job #2960422)

Utilizator Nicolae11Mihaila Nicolae Nicolae11 Data 4 ianuarie 2023 13:02:11
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.99 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.
    Fie cele doua multimi de noduri ale grafului bipartit impartite in doua multimi: grup1 si grup2.
    Acum vine partea de cuplaj: Adaugam doua noduri, sursa = s cu indicele 0 si destinatia = t cu indicele (grup1+grup2+1). Nodul s se conecteaza la
toate nodurile din grup1 printr-o muchie de capacitate 1, iar toate nodurile din grup2 se conecteaza la t printr-o muchie de capacitate 1. Aplicam
algoritmul de max flow. Fluxul maxim este egal cu numarul maxim de cuplaje realizabile. Potrivirile dintre nodurile din grup1 si grup2 vor fi
identificate prin muchiile care respecta o anumita proprietate.

Complexitate:
Fie n = numarul de noduri, m = numarul de muchii
Timp: O(n*m^2) ///totusi, avem optimizarea cu arborele BFS
Memorie: O(n+m) ///array de vizitati pentru noduri + listele de adiacenta
*/
#include <bits/stdc++.h>
using namespace std;
ifstream f("cuplaj.in");
ofstream g("cuplaj.out");
struct muchie
{
    int cap1;
    int cap2;
    int capacit;
    int pos;
};
int n,m,e,grup1,grup2,s,t;
vector<bool> viz;
vector<int> parinte;
vector<vector<int>> liste;
vector<muchie> muchii;

void addMuchie(int x, int y)
{
    muchie aux;
    int dim=(int)muchii.size();
    liste[y].push_back(dim+1);
    aux.cap1=x;
    aux.cap2=y;
    aux.capacit=1;
    aux.pos=dim+1;
    muchii.push_back(aux);
    liste[x].push_back(dim);
    aux.cap1=y;
    aux.cap2=x;
    aux.capacit=0;
    aux.pos=dim;
    muchii.push_back(aux);
}

bool bfs()
{
    parinte.clear();
    parinte.resize(n);
    viz.clear();
    viz.resize(n,false);
    viz[s]=true;
    queue<int> q;
    q.push(s);
    while(!q.empty())
    {
        int act=q.front();
        q.pop();
        if(act!=t)
            for(int i : liste[act])
            {
                muchie cMuchie=muchii[i];
                if (!viz[cMuchie.cap2] && cMuchie.capacit!=0)
                {
                    parinte[cMuchie.cap2]=i;
                    q.push(cMuchie.cap2);
                    viz[cMuchie.cap2]=true;
                }
            }
    }
    return viz[t];
}

int MF(int s, int t)
{
    int maxFlow=0;
    while(bfs())
    {
        for(int i : liste[t])
        {
            if(viz[muchii[i].cap2] && muchii[muchii[i].pos].capacit!=0)
            {
                int minCapacit=1000000;
                muchie cMuchie=muchii[i];
                parinte[t]=cMuchie.pos;
                int j=t;
                while(j!=s)
                {
                    minCapacit=min(minCapacit,muchii[parinte[j]].capacit);
                    j=muchii[parinte[j]].cap1;
                }
                j=t;
                while(j!=s)
                {
                    muchii[muchii[parinte[j]].pos].capacit+=minCapacit;
                    muchii[parinte[j]].capacit-=minCapacit;
                    j=muchii[parinte[j]].cap1;
                }
                maxFlow+=minCapacit;
            }
        }
    }
    return maxFlow;
}

int main()
{
    f>>grup1>>grup2>>e;
    n=grup1+grup2+2;
    s=0;
    t=n-1;
    liste.resize(n);
    int x,y;
    for(int i=0;i<e;i++)
    {
        f>>x>>y;
        addMuchie(x,y+grup1);
    }
    for(int i=1;i<=grup1;i++)
        addMuchie(s,i);
    for(int i=1;i<=grup2;i++)
        addMuchie(i+grup1,t);
    g<<MF(s,t)<<'\n';
    for (muchie i: muchii)
        if(i.cap1<i.cap2 && i.cap1!=0 && i.cap2!=t && i.capacit==0)
            g<<i.cap1<<' '<<i.cap2-grup1<<'\n';
    return 0;
}