Cod sursa(job #2962140)

Utilizator David_PatranjelDavid Patranjel David_Patranjel Data 7 ianuarie 2023 20:35:10
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.43 kb
#include <iostream>
#include <vector>
#include <fstream>
#include <queue>
#include <numeric>
#include <algorithm>
#define INFINITY 999999999
using namespace std;

struct edge_info{
    int node, f;
};
int noNodes;
int noEdges;
int l, r, e;
vector<vector<edge_info>> graf_c;
vector<vector<edge_info>> graf_t;
vector<edge_info> edges;
bool constructSTNesaturatedBF(int s, int t, vector<vector<edge_info>>& graf_t, vector<int>& tata, vector<bool>& viz);
void revizFlux(int s, int t, vector<int>& tata, int& ip);
int EndmondsKarp(int fin);
void citireFisier();
void testEdmondsKarp();
int BS(int u, int v, vector<vector<edge_info>>& search_vector);
bool sortfunc(edge_info a, edge_info b);

int main() {
    citireFisier();
    testEdmondsKarp();
    return 0;
}

void citireFisier(){
    int x, y;
    ifstream fin("cuplaj.in");
    fin>>l>>r>>e;
    noEdges = l + r + e;
    noNodes = l + r + 2;
    graf_c.resize(noNodes + 1);
    for(int i = 1; i <= e; ++i){
        fin>>x>>y;
        edge_info init_edge; init_edge.node = y + l; init_edge.f = 0;
        graf_c[x].push_back(init_edge);
    }

    for(int i = 1; i <= l; ++i){
        edge_info init_edge; init_edge.node = i; init_edge.f = 0;
        graf_c[0].push_back(init_edge);
    }

    for(int i = 1; i <= r; ++i){
        edge_info init_edge; init_edge.node = l + r + 1; init_edge.f = 0;
        graf_c[i + l].push_back(init_edge);
    }

    for(auto& node_edge:graf_c){
        sort(node_edge.begin(), node_edge.end(), sortfunc);
    }

    fin.close();
}

void testEdmondsKarp(){
    ofstream fout("cuplaj.out");
    fout<<EndmondsKarp(noNodes)<<endl;
    for(int i = 1; i <= l; ++i){
        for(auto& u:graf_c[i]){
            if(u.f == 1){
                fout<<i<<" "<<u.node - l<<endl;
            }
        }
    }
    fout.close();
}

bool constructSTNesaturatedBF(int s, int t, vector<vector<edge_info>>& graf_t, vector<int>& tata, vector<bool>& viz){
    int i, v, c;
    fill(viz.begin(), viz.end(), false);
    queue<int> C;
    C.push(s);
    viz[s] = true;

    while(!C.empty()) {
        i = C.front();
        if(i == t){
            C.pop();
            continue;
        }
        for(auto& j:graf_c[i]) {
            v = j.node; c = 1;
            if (!viz[v] && c > j.f) { ///arc direct
                C.push(v);
                viz[v] = 1;
                tata[v] = i;
                if(v == t)
                    return true;
            }
        }
        for(auto& j:graf_t[i]){
            v = j.node;
            if(viz[v] == 0 && j.f > 0){   ///arc invers
                C.push(v);
                viz[v] = 1;
                tata[v] = -i;
                if(v == t)
                    return true;
            }
        }
        C.pop();
    }
    if(viz[t])
        return true;
    return false;
}
void revizFlux(int s, int t, vector<int>& tata, int& ip){
    int nod = t, parent, mod_nod, poz, poz_t;
    do{
        mod_nod = abs(nod);
        parent = tata[mod_nod];
        if(parent >= 0){
            poz = BS(parent, mod_nod, graf_c);
            poz_t = BS(mod_nod, parent, graf_t);
            graf_c[parent][poz].f += ip;
            graf_t[mod_nod][poz_t].f += ip;
        }else{
            poz = BS(mod_nod, abs(parent), graf_c);
            poz_t = BS(abs(parent), mod_nod, graf_t);
            graf_c[mod_nod][poz].f -= ip;
            graf_t[abs(parent)][poz_t].f -= ip;
        }
        nod = tata[mod_nod];
    }while(abs(nod) != s);
}
int EndmondsKarp(int fin){
    short offset = 1;
    int sum = 0, s = 1 - offset, t = fin - offset, minim;
    graf_t.resize(noNodes + 1);
    vector<bool> viz(noNodes + 1, false);
    vector<int> tata(noNodes + 1, 0);

    for(int i = 1 - offset; i <= noNodes - offset; ++i){
        for(auto& j:graf_c[i]){
            edge_info new_edge;
            new_edge.node = i; new_edge.f = j.f;
            graf_t[j.node].push_back(new_edge);
        }
    }

    while(constructSTNesaturatedBF(s, t, graf_t, tata, viz)){
        for (auto& nodex: graf_t[t]) {
            int node = nodex.node;
            int poz = BS(nodex.node, t, graf_c);
            if (graf_c[node][poz].f || !viz[node])
                continue;

            tata[t] = node;
            minim = INFINITY;

            int nod = t, parent, mod_nod;
            do{
                mod_nod = abs(nod);
                parent = tata[mod_nod];
                if(parent >= 0){
                    poz = BS(parent, mod_nod, graf_c);
                    minim = min(minim, 1 - graf_c[parent][poz].f);
                }else{
                    poz = BS(mod_nod, abs(parent), graf_c);
                    minim = min(minim, graf_c[mod_nod][poz].f);
                }
                nod = tata[mod_nod];
            }while(abs(nod) != s && minim != 0);
            if (minim == 0)
                continue;

            revizFlux(s, t, tata, minim);
            sum += minim;
        }
    }
    return sum;
}

int BS(int u, int v, vector<vector<edge_info>>& search_vector){
    int left = 0, right = search_vector[u].size() - 1, mid, curent;
    while(left <= right){
        mid = left + (right - left) / 2;
        curent = search_vector[u][mid].node;
        if(curent == v) return mid;
        else if(curent < v) left = mid + 1;
        else right = mid - 1;
    }
}

bool sortfunc(edge_info a, edge_info b) {
    return a.node < b.node;
}