Cod sursa(job #3225091)

Utilizator Dragono63Stanciu Rares Stefan Dragono63 Data 16 aprilie 2024 21:34:13
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.85 kb
#ifndef LOCAL
    #pragma GCC optimize("O3")
    #pragma GCC target("avx2")
#endif

#ifdef LOCAL
    #define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>
#define pb push_back
#define pii pair<int, int>
using ll = long long;
using ci = const int;
using cll = const long long;

using namespace std;

const int INF = 1e9 + 7;
/*******************************/
// INPUT / OUTPUT

#ifndef LOCAL
    ifstream in("fmcm.in");
    ofstream out("fmcm.out");
    #define cin in
    #define cout out
#endif
/*******************************/
/// GLOBAL DECLARATIONS

int N, M, S, D;

struct Muchie
{
    int from, to, cap, cost;
};

struct Graf
{
    int n;
    vector <int> dist, pre;
    vector <vector <int>> adj;
    vector <Muchie> muchii;

    Graf(int _n)
    {
        n = _n;
        dist.resize(n);
        pre.resize(n);
        adj.resize(n);
    }

    inline void adauga_muchie(int from, int to, int cap, int cost)
    {
        adj[from].push_back(muchii.size());
        muchii.push_back({from, to, cap, cost});

        adj[to].push_back(muchii.size());
        muchii.push_back({to, from, 0, -cost});
    }

    inline bool bellman_ford(int sursa, int dest)
    {
        vector <bool> in_queue(n, false);

        for (int i = 0 ; i < n ; ++ i) dist[i] = INF;
        dist[sursa] = 0; in_queue[sursa] = true;
        queue <int> q; q.push(sursa);
        int node;
        Muchie u;
        while (!q.empty())
        {
            node = q.front();
            in_queue[node] = false;
            q.pop();

            for (auto i: adj[node])
            {
                u = muchii[i];
                if (u.cap && dist[u.to] > dist[node] + u.cost)
                {
                    dist[u.to] = dist[node] + u.cost;

                    if (!in_queue[u.to])
                    {
                        in_queue[u.to] = true;
                        q.push(u.to);
                    }
                }
            }
        }

        return dist[dest] != INF;
    }

   inline bool dijkstra(int sursa, int dest)
    {
        vector <bool> vis(n, false);
        vector <int> dist_reala(n), dist_falsa(n, INF);
        for (int i = 0 ; i < n ; ++ i)
        {
            dist_reala[i] = dist[i];
            pre[i] = -1;
        }

        priority_queue <pii> pq; pq.push({0, sursa});
        dist_falsa[sursa] = dist[sursa] = 0;
        
        int node;
        while (!pq.empty())
        {
            node = pq.top().second;
            pq.pop();

            Muchie u;
            if (!vis[node])
            {
                vis[node] = true;
                for (auto i: adj[node])
                {
                    u = muchii[i];

                    if (u.cap && !vis[u.to] && dist_falsa[u.to] > dist_falsa[node] + u.cost + dist_reala[node] - dist_reala[u.to])
                    {
                        pre[u.to] = i;
                        dist_falsa[u.to] = dist_falsa[node] + u.cost + dist_reala[node] - dist_reala[u.to];
                        dist[u.to] = dist[node] + u.cost;
                        pq.push({-dist_falsa[u.to], u.to});
                    }
                }
            }
        }

        return dist_falsa[dest] != INF;
    }


    inline pii push_flux(int sursa, int dest)
    {
        int flux = INF, cost = 0;
        for (int node = dest; node != sursa; node = muchii[pre[node]].from)
        {
            flux = min(flux, muchii[pre[node]].cap);
            cost += muchii[pre[node]].cost;
        }

        for (int node = dest ; node != sursa ; node = muchii[pre[node]].from)
        {
            muchii[pre[node]].cap -= flux;
            muchii[pre[node] ^ 1].cap += flux;
        }

        return {flux, flux * cost};
    }

    inline pii afla_flux(int sursa, int dest)
    {
        bool ok = bellman_ford(sursa, dest);
        if (!ok) return {0, 0};

        int cicluri = 0;
        pii sol = {0, 0}, ret;
        while (dijkstra(sursa, dest))
        {
            ++ cicluri;
            ret = push_flux(sursa, dest);
            sol.first += ret.first; sol.second += ret.second;
        }
        return sol;
    }
};
/*******************************/
/// FUNCTIONS

void ReadInput();
void Solution();
void Output();
/*******************************/
///-------------------------------------
inline void ReadInput()
{
    cin >> N >> M >> S >> D;
    S --; D --;
}
///-------------------------------------
inline void Solution()
{
    Graf graf = Graf(N);

    int a, b, cap, cost;
    for (int i = 0 ; i < M ; ++ i)
    {
        cin >> a >> b >> cap >> cost;

        a --; b --;
        graf.adauga_muchie(a, b, cap, cost);
    }

    cout << graf.afla_flux(S, D).second;
}
///-------------------------------------
inline void Output()
{
}
///-------------------------------------
int main()
{
    #ifndef LOCAL
        ios::sync_with_stdio(false);
        cin.tie(NULL);
        cout.tie(NULL);
    #endif
    ReadInput();
    Solution();
    Output();
    return 0;
}