Cod sursa(job #3361310)

Utilizator FlaviuuuFlaviu Flaviuuu Data 23 iulie 2026 00:11:50
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.69 kb
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream cin("fmcm.in");
ofstream cout("fmcm.out");
const int NMAX = 350;
const int MMAX = 12500;
const int INF = 1e9;
struct maxFlow{
    int n;
    int source, sink;
    struct edge{
        int x, y;
        int cap, cost;
        int w;
    };
    edge e[2 * MMAX + 5];
    vector<int> v[NMAX + 5];
    int numberOfEdges = 0;
    int pot[NMAX + 5];
    int d[NMAX + 5];
    void init(int x, int s, int t)
    {
        n = x;
        source = s;
        sink = t;
    }
    void addEdge(int x, int y, int z, int c)
    {
        numberOfEdges++;
        e[numberOfEdges].cap = z;
        v[x].push_back(numberOfEdges);
        e[numberOfEdges].x = x; e[numberOfEdges].y = y;
        e[numberOfEdges].cost = c;
        numberOfEdges++;
        e[numberOfEdges].cap = 0;
        v[y].push_back(numberOfEdges);
        e[numberOfEdges].x = y; e[numberOfEdges].y = x;
        e[numberOfEdges].cost = -c;
    }
    void bellmanFord()
    {
        //Valorile initiale ale vectorului d (si implicit ale vectorului de potentiale).
        for(int i = 1; i <= n; i++)
            d[i] = INF;
        d[source] = 0;
        for(int times = 1; times <= n; times++)
            for(int i = 1; i <= numberOfEdges; i++)
                if(e[i].cap && d[e[i].x] != INF)
                    d[e[i].y] = min(d[e[i].y], d[e[i].x] + e[i].cost);
        for(int i = 1; i <= n; i++)
            pot[i] = d[i];
    }
    void buildW()
    {
        for(int i = 1; i <= numberOfEdges; i++)
            e[i].w = (e[i].cost + pot[e[i].x] - pot[e[i].y]);
    }
    int prev[NMAX + 5];
    bool getAugmentingPath()
    {
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
        for(int i = 1; i <= n; i++)
            d[i] = INF;
        d[source] = 0;
        prev[source] = 0;
        pq.push({0, source});
        int nod, cost;
        bool reachedSink = 0;
        while(!pq.empty())
        {
            cost = pq.top().first;
            nod = pq.top().second;
            pq.pop();      
            if(nod == sink)
                reachedSink = 1;
            if(cost == d[nod])
            {
                for(int& it : v[nod])
                    if(e[it].cap && cost + e[it].w < d[e[it].y])
                        {d[e[it].y] = cost + e[it].w; prev[e[it].y] = it; pq.push({d[e[it].y], e[it].y});}
            }   
        }
        return reachedSink;
    }
    int maxFlow = 0;
    int minCost = 0;
    void pushFlow()
    {
        int nod = sink;
        int mini = INF;
        while(prev[nod])
        {
            mini = min(mini, e[prev[nod]].cap);
            nod = (e[prev[nod]].x == nod ? e[prev[nod]].y : e[prev[nod]].x);
        }
        nod = sink;
        while(prev[nod])
        {
            e[prev[nod]].cap -= mini;
            e[((prev[nod] & 1) ? prev[nod] + 1 : prev[nod] - 1)].cap += mini; //Crestem capacitatea pe muchia inversa.
            minCost += (mini * e[prev[nod]].cost);
            nod = (e[prev[nod]].x == nod ? e[prev[nod]].y : e[prev[nod]].x);
        }
        maxFlow += mini;
    }
    int getMinCost()
    {
        bellmanFord();
        buildW();
        while(getAugmentingPath())
        {
            pushFlow();
            for(int i = 1; i <= n; i++)
                pot[i] += d[i];
            buildW();
        }
        return minCost;
    }
};
maxFlow flow;
int n, m, s, d;
void readInput()
{
    cin >> n >> m >> s >> d;
    int x, y, z, c;
    flow.init(n, s, d);
    for(int i = 1; i <= m; i++)
    {
        cin >> x >> y >> z >> c;
        flow.addEdge(x, y, z, c);
    }
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    readInput();
    cout << flow.getMinCost();
    return 0;
}