Cod sursa(job #2987099)

Utilizator matei.tudoseMatei Tudose matei.tudose Data 1 martie 2023 22:07:27
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.68 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

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

const int NMAX = 350, INF = 0x3f3f3f3f;

vector<int> graf[NMAX + 5];
queue<int> coada;
int N, M, capacitate[NMAX + 5][NMAX + 5], flow[NMAX + 5][NMAX + 5], tata_de[NMAX + 5], cost[NMAX + 5][NMAX + 5], dist[NMAX + 5];
int startNod, endNod;

// Implementare Bellman-Ford optimizat cu coada a.k.a SPFA

bool bellmanFord()
{
    memset(tata_de, 0, sizeof tata_de);
    memset(dist, INF, sizeof dist);
    coada.push(startNod);
    dist[startNod] = 0;
    while (!coada.empty())
    {
        int nod_curent = coada.front();
        coada.pop();
        for (int i = 0; i < graf[nod_curent].size(); i++)
        {
            int vecin = graf[nod_curent][i];
            if (capacitate[nod_curent][vecin] - flow[nod_curent][vecin] > 0 && dist[vecin] > dist[nod_curent] + cost[nod_curent][vecin])
            {
                dist[vecin] = dist[nod_curent] + cost[nod_curent][vecin];
                tata_de[vecin] = nod_curent;
                coada.push(vecin);
            }
        }
    }
    return dist[endNod] != INF;
}

int main()
{
    fin >> N >> M >> startNod >> endNod;
    for (int i = 0; i < M; i++)
    {
        int from, to, capacity, cost_muchie;
        fin >> from >> to >> capacity >> cost_muchie;
        graf[from].push_back(to);
        graf[to].push_back(from);
        capacitate[from][to] = capacity;
        cost[from][to] = cost_muchie;
        // Ca sa ne intoarcem ca si cum nu am fi fost prin nod
        cost[to][from] = -cost_muchie;
    }
    int max_flow = 0;
    while (bellmanFord())
    {
        // Calculam flow-ul maxim pe care il putem scadea pe traseu, cu optimizarea
        // ca vom face asta din parintii nodului endNod pentru a economisi rulari de B-F
//        for (int i = 0; i < graf[endNod].size(); i++)
//        {
//            int fluxMin = INT32_MAX, vecin = graf[endNod][i];
//            // Daca nu exista traseu prin vecinul finalului sau nu mai exista flow pana la nodul final
//            // Poate exista muchie directa start -> end, iar start nu are tata (caz special)
//            if ((capacitate[vecin][endNod] - flow[vecin][endNod] <= 0) || (tata_de[vecin] == 0 && vecin != startNod))
//                continue;
//            if (vecin == startNod)
//            {
//                fluxMin = capacitate[startNod][endNod] - flow[startNod][endNod];
//                flow[startNod][endNod] -= fluxMin;
//                flow[endNod][startNod] += fluxMin;
//                continue;
//            }
//            fluxMin = capacitate[vecin][endNod] - flow[vecin][endNod];
//            while (vecin != startNod)
//            {
//                fluxMin = min(fluxMin, capacitate[tata_de[vecin]][vecin] - flow[tata_de[vecin]][vecin]);
//                vecin = tata_de[vecin];
//            }
//            vecin = graf[endNod][i];
//            while (vecin != startNod)
//            {
//                flow[tata_de[vecin]][vecin] -= fluxMin;
//                flow[vecin][tata_de[vecin]] += fluxMin;
//                vecin = tata_de[vecin];
//            }
//            max_flow += fluxMin * dist[endNod];
//        }

        int fluxMin = INT32_MAX;
        int nod = endNod;
        while (nod != startNod)
        {
            fluxMin = min(fluxMin, capacitate[tata_de[nod]][nod] - flow[tata_de[nod]][nod]);
            nod = tata_de[nod];
        }
        nod = endNod;
        while (nod != startNod)
        {
            flow[tata_de[nod]][nod] += fluxMin;
            flow[nod][tata_de[nod]] -= fluxMin;
            nod = tata_de[nod];
        }
        max_flow += fluxMin * dist[endNod];
    }
    fout << max_flow << "\n";
    return 0;
}