Cod sursa(job #2950387)

Utilizator vladadAndries Vlad Andrei vladad Data 3 decembrie 2022 16:57:58
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.37 kb
#include <bits/stdc++.h>
using namespace std;
ifstream f("fmcm.in");
ofstream g("fmcm.out");
const int inf = 1e9;
int t;
int n, m;
int source, destination;

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

vector<Edge> edges;
vector<vector<int>> poz;
vector<int> potential;
vector<int> dist2, dist;
vector<int> dad;

struct cmp
{
    bool operator () (const int &u, const int &v)
    {
        return dist2[u] > dist2[v];
    }
};

void addEdge(int u, int v, int cap, int cost, int flow = 0)
{
    int m = edges.size();
    edges.push_back({u, v, cap, cost, flow});
    edges.push_back({v, u, 0, -cost, 0});
    poz[u].push_back(m); //pozitia
    poz[v].push_back(m + 1);
}

void bf()
{
    queue<int> q;
    vector<bool> inQ(n + 1); //in queue
    dist = vector<int> (n + 1, inf);
    dist[source] = 0;
    q.push(source);
    inQ[source] = 1;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        inQ[u] = 0;
        for(const auto &it: poz[u])
        {
            int v = edges[it].v;
            int cap = edges[it].cap;
            int cost = edges[it].cost;
            if(cap > 0 && dist[v] > dist[u] + cost)
            {
                dist[v] = dist[u] + cost;
                if(!inQ[v])
                {
                    q.push(v);
                    inQ[v] = 1;
                }
            }
        }
    }
}

bool dij()
{
    priority_queue<int, vector<int>, cmp> pq;
    vector<bool> inQ(n + 1);
    dad = vector<int> (n + 1);
    potential = dist;
    dist = dist2 = vector<int> (n + 1, inf);
    dist[source] = dist2[source] = 0;
    pq.push(source);
    inQ[source] = 1;
    while(!pq.empty())
    {
        int u = pq.top();
        pq.pop();
        inQ[u] = 0;
        for(const auto &it: poz[u])
        {
            int v = edges[it].v;
            int cap = edges[it].cap;
            int cost = edges[it].cost;
            int flow = edges[it].flow;
            if(cap - flow > 0 && dist2[v] + potential[v] > dist2[u] + potential[u] + cost)
            {
                dist2[v] = dist2[u] + potential[u] + cost - potential[v];
                dist[v] = dist[u] + cost;
                dad[v] = it;

                if(!inQ[v])
                {
                    pq.push(v);
                    inQ[v] = 1;
                }
            }
        }
    }
    return dist2[destination] != inf;
}
int main()
{
    f >> n >> m >> source >> destination;
    edges = vector<Edge> (0);
    poz = vector<vector<int>> (n + 1);
    for(int i = 1; i <= m; i++)
    {
        int u, v, c, z;
        f >> u >> v >> c >> z;
        addEdge(u, v, c, z);
    }
    bf();
    int maxFlow = 0, minCost = 0;
    while(dij())
    {
        int flow = inf, cost = 0;
        for(int u = destination; u != source; u = edges[dad[u]].u) //merg in sens invers de la destinatie la sursa
        {
            flow = min(flow, edges[dad[u]].cap - edges[dad[u]].flow); //actualizez fluxul
            cost += edges[dad[u]].cost;
        }
        maxFlow += flow; //adun la raspuns
        minCost += cost * flow;
        for(int u = destination; u != source; u = edges[dad[u]].u)
        {
            edges[dad[u]].flow += flow;
            edges[dad[u] ^ 1].flow -= flow;
        }
    }
    g << minCost << '\n';
    ///Complexitate: O(n*m*m*log(n))
    return 0;
}