Cod sursa(job #3287416)

Utilizator Turcanu_DavidTurcanu David Turcanu_David Data 17 martie 2025 22:06:06
Problema Flux maxim de cost minim Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.28 kb
#include <bits/stdc++.h>
#pragma GCC optimize("O3", "Ofast", "unroll-loops")

using namespace std;

using ll = long long;
// #define int ll
using pii = pair<int, int>;

const int MOD = 1e9 + 7;
const int INF = 1e9;
const int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1}; // N S E V
const int MAXN = 305 + 5;

struct fmcm
{
    struct Edge
    {
        int u, v, cap, cost;
    };

    vector<Edge> e;
    vector<vector<int>> adj;
    vector<int> fd;
    int cnt = 0;

    void init()
    {
        e.clear();
        adj.clear();
        fd.clear();
        cnt = 0;
    }

    int add_node()
    {
        adj.push_back({});
        fd.push_back(0);
        return cnt++;
    }

    void add_edge(int u, int v, int cap, int cost)
    {
        adj[u].push_back(e.size());
        e.push_back({u, v, cap, cost});
        adj[v].push_back(e.size());
        e.push_back({v, u, 0, -cost});
    }

    void bellman(int s)
    {
        for(int i = 0; i < cnt; i++)
            fd[i] = INF;
        fd[s] = 0;
        for(int _ = 0; _ < cnt; _++)
        {
            for(auto [u, v, cap, cost] : e)
            {
                if(cap)
                    fd[v] = min(fd[v], fd[u] + cost);
            }
        }
        for(auto [u, v, cap, cost] : e)
        {
            if(cap && cost + fd[u] - fd[v] < 0)
            {
                assert(false);
            }
        }
    }

    int dijkstra(int s, int t)
    {
        priority_queue<pii> pq; // cost, nod
        pq.push({0, s});
        vector<int> dist;
        dist.assign(cnt, INF);
        vector<int> parent; // tin edgeul
        parent.resize(cnt);
        dist[s] = 0;
        while(!pq.empty())
        {
            int d = -pq.top().first, u = pq.top().second;
            pq.pop();
            if(d > dist[u])
                continue;
            for(int j : adj[u])
            {
                int newd = d + e[j].cost + fd[u] - fd[e[j].v];
                if(e[j].cap && newd < dist[e[j].v])
                {
                    dist[e[j].v] = newd;
                    parent[e[j].v] = j;
                    pq.push({-newd, e[j].v});
                }
            }
        }
        if(dist[t] == INF) // fail
            return 0;
        for(int i = 0; i < cnt; i++)
        {
            dist[i] += fd[i];
        }
        int flow = INF;
        for(int i = t; i != s; )
        {
            flow = min(flow, e[parent[i]].cap);
            i = e[parent[i]].u;
        }
        for(int i = t; i != s; )
        {
            e[parent[i]].cap -= flow;
            e[parent[i] ^ 1].cap += flow;
            i = e[parent[i]].u;
        }
        return flow * dist[t];
    }

    int flow(int s, int t)
    {
        bellman(s);
        int ans = 0;
        int res = 0;
        while(res = dijkstra(s, t))
        {
            ans += res;
            if(rand() % 10)
                bellman(s);
        }
        return ans;
    }
};

fmcm fm;

int n, m, s, d;

int32_t main()
{
    #ifndef LOCAL
        ifstream cin("fmcm.in");
        ofstream cout("fmcm.out");
    #endif
    cin >> n >> m >> s >> d;
    for(int i = 0; i < n; i++)
    {
        fm.add_node();
    }
    for(int i = 1; i <= m; i++)
    {
        int x, y, c, z;
        cin >> x >> y >> c >> z;
        fm.add_edge(x - 1, y - 1, c, z);
    }
    cout << fm.flow(s - 1, d - 1);
    return 0;
}