Cod sursa(job #2962363)

Utilizator AdelaCorbeanuAdela Corbeanu AdelaCorbeanu Data 8 ianuarie 2023 14:09:09
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.27 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
ifstream f("cuplaj.in");
ofstream g("cuplaj.out");
int n,m,e, sursa, destinatie,nr,flux;
struct muchie{
    int pleaca,ajunge,capacitate,pozitie;
};
vector<muchie> graf;
vector<vector<int>> ind; // retine pentru fiecare nod indicii muchiilor incidente
vector<bool> vizitat;
vector<int> tata;
bool bfs(){
    tata.clear();
    tata.resize(nr+1);
    vizitat.clear();
    vizitat.resize(nr+1,false);
    vizitat[sursa]= true;
    queue<int> coada;
    coada.push(sursa);
    while(!coada.empty()){
        int nod=coada.front();
        coada.pop();
        if(nod!=destinatie){
            for (int i : ind[nod]) {
                muchie mc = graf[i];
                if(!vizitat[mc.ajunge] && mc.capacitate!=0){
                    tata[mc.ajunge]=i;
                    coada.push(mc.ajunge);
                    vizitat[mc.ajunge]=true;
                }
            }
        }
    }
    return vizitat[destinatie];
}
int main() {
    // Complexitatea este O(n*m*m)
    int x,y;
    f>>n>>m>>e;
    nr=n+m+2;
    sursa=0;
    destinatie=nr-1;
    ind.resize(nr+1);
    for (int i = 0; i < e; ++i) {
        f>>x>>y;
        int poz=graf.size();
        muchie mc;
        ind[y+n].push_back(poz+1); // adaugam muchia
        mc={x,y+n,1,poz+1};
        graf.push_back(mc);
        ind[x].push_back(poz); // adaugam muchia inversa
        mc={y+n,x,0,poz};
        graf.push_back(mc);
    }
    // Adaugam muchii din sursa in nodurile din multimea L
    for (int i = 1; i <= n; ++i) {
        int poz=graf.size();
        muchie mc;
        ind[i].push_back(poz+1);
        mc={sursa,i,1,poz+1};
        graf.push_back(mc);
        ind[sursa].push_back(poz);
        mc={i,sursa,0,poz};
        graf.push_back(mc);
    }
    // Adaugam muchii din nodurile din multimea R in destinatie
    for (int i = 1; i <= m; ++i) {
        int poz=graf.size();
        muchie mc;
        ind[destinatie].push_back(poz+1);
        mc={i+n,destinatie,1,poz+1};
        graf.push_back(mc);
        ind[i+n].push_back(poz);
        mc={destinatie,i+n,0,poz};
        graf.push_back(mc);
    }

    while(bfs()){ // cat timp exista un drum din sursa in destinatie
        for(int i : ind[destinatie]){
            muchie mc = graf[i];
            if(vizitat[mc.ajunge] && graf[mc.pozitie].capacitate!=0){
                tata[destinatie]=mc.pozitie;
                int minim=INT_MAX; // calculam minimul din drum
                for (int nod = destinatie; nod != sursa; nod = graf[tata[nod]].pleaca) {
                    minim = min(minim, graf[tata[nod]].capacitate);
                }
                for (int nod = destinatie; nod != sursa; nod = graf[tata[nod]].pleaca){
                    graf[tata[nod]].capacitate -= minim; // actualizam graful rezidual
                    graf[graf[tata[nod]].pozitie].capacitate += minim;
                }
                flux += minim;
            }
        }
    }
    g<<flux<<'\n';
    for(muchie mc :graf){
        // afisam muchiile saturate care au nodul de plecare in multimea L si cel in care ajunge din multimea R
        if(mc.pleaca<mc.ajunge && mc.pleaca!=sursa && mc.ajunge!=destinatie && mc.capacitate==0){
            g<<mc.pleaca<<' '<<mc.ajunge-n<<'\n';
        }
    }
    return 0;
}