Cod sursa(job #2961411)

Utilizator Andoss1710Balanica Andrei Andoss1710 Data 6 ianuarie 2023 14:34:58
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.96 kb
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");

int n, m, e, N;
//int cap[1001][1001];//capacitatea muchiilor
int viz[20001];
pair<int, int>tata[20001];//ca sa retin nodurile vizitate si tatal nodurilor pentru reconstruirea drumului
vector<vector<pair<pair<int, int>, int>>> lista(20001);//lista de muchii

int bfs(){//bfs pentru aflarea existentei drumului de crestere
    queue<int> coada;
    coada.push(0);
    for(int i = 0; i <= N; i++){
        tata[i] = {-1, -1};
        viz[i] = 0;
}
    viz[0]++;

    while(coada.size()!=0){
        int nod_cur = coada.front();
        //cout<<nod_cur<<" "<<tata[nod_cur]<<" ";
        if(nod_cur == N)//daca am ajuns la final inseamna ca am gasit un drum de crestere
            return 1;
        int cnt = 0;
        for(int i = 0; i < lista[nod_cur].size(); i++){
            int nod_vec = lista[nod_cur][i].first.first;
            if(lista[nod_cur][i].first.second > 0 && viz[nod_vec] == 0){//daca am gasit un nod prin care nu am mai fost care mai are loc, trecem prin el
                viz[nod_vec]++;
                tata[nod_vec] = {nod_cur, cnt};
                coada.push(nod_vec);

            }
            cnt++;
        }
        coada.pop();//scot din coada nodul prin care deja am trecut
    }
    return 0;//nu am gasit
}

int Edmonds_Karp(){
    int max_flux = 0;//fluxul maixim
    while(bfs()){//cat timp avem drum de crestere
        cout<<endl;
        for(int i = 0; i < lista[N].size(); i++){
            int nod_cur = lista[N][i].first.first;
            if(lista[nod_cur][lista[N][i].second].first.second > 0 && viz[nod_cur]){//daca este drum care a dus de la vecinul lui n la n care mai are capacitate
                    //si a fost vizitat in verificarea noastra, atunci reconstituim drumul parcurs
               //vector<pair<int, int>> drum;//reconstituirea drumului
               //drum.push_back(nod_cur, );
               cout<<nod_cur<<" ";
                int minim = 9999999;//bottleneckul nostru
                tata[N] = {nod_cur, lista[N][i].second};
                int drum = N;
               while(tata[drum].first!=-1){
                minim = min(minim, lista[tata[drum].first][tata[drum].second].first.second);
                drum = tata[drum].first;
                //cout<<nod_cur<<" "<<tata[nod_cur]<<endl;
                //drum.push_back(nod_cur);
               }

//               for(int i = 0; i < drum.size(); i++)//vedem care este bottleneckul drumului
//                    if(i == 0){
//                        minim = min(minim, lista[drum[i]][lista[N][drum[i]].second].first.second);
//                        cout<<lista[N][drum[i]].second<<" "<<drum[i]<<endl;
//                    }
//                    else
//                         minim = min(minim, lista[drum[i]][lista[drum[i-1]][drum[i]].second].first.second);

                max_flux += minim;//il adaugam la flux doarece e cea mai mare valoare pe care o putem trece prin acel drum
                drum = N;
                while(tata[drum].first!=-1){
                    lista[tata[drum].first][tata[drum].second].first.second -= minim;
                    lista[drum][lista[tata[drum].first][tata[drum].second].second].first.second += minim;
                    drum = tata[drum].first;
                }
//                for(int i = 0; i < drum.size(); i++){
//                    if(i == 0){
//                        lista[drum[i]][lista[N][drum[i]].second].first.second -= minim;//scadem cap de la muchia de crestere
//                        lista[N][lista[drum[i]][N].second].first.second +=minim;//dar crestem cap muchiei de intoarece
//                    }
//                    else{
//                        lista[drum[i]][lista[drum[i-1]][drum[i]].second].first.second -= minim;
//                        lista[drum[i-1]][lista[drum[i]][drum[i-1]].second].first.second += minim;
//                    }
//
//                }
                cout<<minim<<" ";
            }
           //return 0;
        }
    }
    return max_flux;//fluxul maxim

}


int main()
{
    fin>>n>>m>>e;
    N = n + m + 1;
    for(int i = 0; i < e; i++){
        int u, v;
        fin>>u>>v;
        lista[u].push_back({{v+n ,1}, lista[v+n].size()});
        lista[v+n].push_back({{u, 0}, lista[u].size()-1});
    }
    for(int i = 1; i <= n; i++){
        lista[0].push_back({{i, 1}, lista[i].size()});
        lista[i].push_back({{0, 0}, lista[0].size()-1});
    }
    for(int i = 1; i <= m; i++){
        lista[i+n].push_back({{n+m+1, 1}, lista[N].size()});
        lista[n+m+1].push_back({{i+n, 0}, lista[i+n].size()-1});
    }
    fout<<Edmonds_Karp()<<"\n";

    for(int i = 1; i <= n; i++)
        for(int j = 0; j <lista[i].size(); j++){
            if(lista[i][j].first.second != 1 && lista[i][j].first.first != 0)
                fout<<i<<" "<<lista[i][j].first.first - n<<"\n";
    }
}