Cod sursa(job #3208372)

Utilizator SSKMFSS KMF SSKMF Data 28 februarie 2024 13:58:24
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.31 kb
#include <fstream>
#include <queue>
using namespace std;

ifstream cin ("fmcm.in");
ofstream cout ("fmcm.out");

struct Arc { int nod_vecin , capacitate , cost , urmatorul; } arce[25001]; 
int numar_noduri , capat[351] , distanta[351];
pair <int , int> urmatorul[351];

bool Dijkstra (const int nod_sursa , const int nod_destinatie)
{
    for (int indice = 1 ; indice <= numar_noduri ; indice++)
        { distanta[indice] = 1000000000; urmatorul[indice] = { }; }

    priority_queue < pair <int , int> > optiuni;
    optiuni.push({distanta[nod_sursa] = 0 , nod_sursa});
    while (!optiuni.empty())
    {
        if (distanta[optiuni.top().second] != -optiuni.top().first)
            { optiuni.pop(); continue; }
    
        const int nod_actual = optiuni.top().second;
        optiuni.pop();

        for (int indice = capat[nod_actual] ; indice ; indice = arce[indice].urmatorul) {
            if (distanta[arce[indice].nod_vecin] > distanta[nod_actual] + arce[indice].cost && arce[indice].capacitate) { 
                optiuni.push({-(distanta[arce[indice].nod_vecin] = distanta[nod_actual] + arce[indice].cost) , arce[indice].nod_vecin}); 
                urmatorul[arce[indice].nod_vecin] = {nod_actual , indice};
            }
        }
    }

    return distanta[nod_destinatie] != 1000000000;
}

void Bellman_Ford (const int nod_sursa)
{
    bool in_coada[351] = { };
    for (int indice = 1 ; indice <= numar_noduri ; indice++)
        { distanta[indice] = 1000000000; }

    queue <int> candidati;
    for (candidati.push(nod_sursa) , distanta[nod_sursa] = 0 , in_coada[nod_sursa] = true ; !candidati.empty() ; candidati.pop())
    {
        const int nod_actual = candidati.front();
        for (int indice = capat[nod_actual] ; indice ; indice = arce[indice].urmatorul) {
            if ((indice & 1) && distanta[arce[indice].nod_vecin] > distanta[nod_actual] + arce[indice].cost)
            {
                distanta[arce[indice].nod_vecin] = distanta[nod_actual] + arce[indice].cost;
                if (!in_coada[arce[indice].nod_vecin]) { 
                    candidati.push(arce[indice].nod_vecin); 
                    in_coada[arce[indice].nod_vecin] = true;
                }
            }
        }

        in_coada[nod_actual] = false;
    }
}

int main ()
{
    int numar_arce , nod_sursa , nod_destinatie;
    cin >> numar_noduri >> numar_arce >> nod_sursa >> nod_destinatie;

    for (int indice = 1 , nod_actual ; indice <= numar_arce ; indice++)
    {
        cin >> nod_actual >> arce[indice].nod_vecin >> arce[indice].capacitate >> arce[indice].cost;
        arce[indice].urmatorul = capat[nod_actual];
        capat[nod_actual] = indice;

        indice++;
        numar_arce++;
        arce[indice].nod_vecin = nod_actual;
        arce[indice].cost = -arce[indice - 1].cost;
        arce[indice].urmatorul = capat[arce[indice - 1].nod_vecin];
        capat[arce[indice - 1].nod_vecin] = indice;
        arce[indice].capacitate = 0;
    }
    
    Bellman_Ford(nod_sursa);
    
    for (int nod_actual = 1 ; nod_actual <= numar_noduri ; nod_actual++) {
        for (int indice = capat[nod_actual] ; indice ; indice = arce[indice].urmatorul)
            { arce[indice].cost += distanta[nod_actual] - distanta[arce[indice].nod_vecin]; }
    }

    int flux_total = 0;
    long long cost_total = 0;
    const int termen = distanta[nod_destinatie];
    while (Dijkstra(nod_sursa , nod_destinatie))
    {
        int flux_actual = INT32_MAX , cost_actual = 0;
        for (int nod_actual = nod_destinatie ; nod_actual != nod_sursa ; nod_actual = urmatorul[nod_actual].first)
            { flux_actual = min(flux_actual , arce[urmatorul[nod_actual].second].capacitate); cost_actual += arce[urmatorul[nod_actual].second].cost; }
            
        for (int nod_actual = nod_destinatie ; nod_actual != nod_sursa ; nod_actual = urmatorul[nod_actual].first)
            { arce[urmatorul[nod_actual].second].capacitate -= flux_actual; arce[urmatorul[nod_actual].second & 1 ? urmatorul[nod_actual].second + 1 : urmatorul[nod_actual].second - 1].capacitate += flux_actual; }

        cost_total += 1LL * flux_actual * cost_actual;
        flux_total += flux_actual;
    }
    
    cout << (cost_total += 1LL * flux_total * termen);
    cout.close(); cin.close();
    return 0;
}