Cod sursa(job #2297572)

Utilizator Tataru_AdelinTataru Adelin Tataru_Adelin Data 6 decembrie 2018 02:33:00
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.25 kb
#include <bits/stdc++.h>

using namespace std;

class Unit
{
public:
    int cap;
    int cost;

public:

    void initialize(int x, int y)
    {
        cap = x;
        cost = y;
    }

    Unit()
    {}

    Unit(int x, int y)
    {
        initialize(x, y);
    }
};

class Node
{
public:
    int node;
    int cost;

public:

    void initialize(int x, int y)
    {
        node = x;
        cost = y;
    }

    Node()
    {}

    Node(int x, int y)
    {
        initialize(x, y);
    }
};

class comp
{
public:
    bool operator() (Node a, Node b)
    {
        return a.cost > b.cost;
    }
};

void reset(vector <int> &v)
{
    for(unsigned i = 0; i < v.size(); i++)
        v[i] = 0;
}

void bellman(int start, int dest, vector <int> &dist, vector <vector <int>> &path, vector <vector <Unit>> &flux)
{
    queue <int> q;
    vector <bool> in_q(path.size(), false);

    dist[start] = 0;
    q.push(start);


    int current, vec;

    while(!q.empty())
    {
        current = q.front();
        q.pop();
        in_q[current] = false;

        for(unsigned i = 0; i < path[current].size(); i++)
        {
            vec = path[current][i];
            if(dist[vec] > dist[current] + flux[current][vec].cost && flux[current][vec].cap > 0)
            {
                dist[vec] = dist[current] + flux[current][vec].cost;
                if(!in_q[vec])
                {
                    q.push(vec);
                    in_q[vec] = true;
                }
            }
        }
    }
}

bool dijkstra(int start, int dest, vector <int> &parent, vector <int> &dist, vector <vector <int>> &path, vector <vector <Unit>> &flux)
{
    priority_queue <Node, vector <Node>, comp> q;
    vector <int> dist_d(dist.size(), numeric_limits<int>::max());
    vector <int> dist_u(dist.size());

    vector <bool> viz(path.size(), false);

    reset(parent);

    dist_d[start] = 0;
    q.push(Node(start, 0));

    Node current, vec;

    while(!q.empty())
    {
        current = q.top();
        q.pop();


        //if(current.cost <= dist_d[current.node])
        if(!viz[current.node])
        for(unsigned i = 0; i < path[current.node].size(); i++)
        {
            vec.node = path[current.node][i];
            if(dist_d[vec.node] > current.cost + flux[current.node][vec.node].cost + dist[current.node] - dist[vec.node] && flux[current.node][vec.node].cap > 0)
            {
                dist_d[vec.node] = current.cost + flux[current.node][vec.node].cost + dist[current.node] - dist[vec.node];
                dist_u[vec.node] = dist_u[current.node] + flux[current.node][vec.node].cost;

                parent[vec.node] = current.node;

                q.push(Node(vec.node, dist_d[vec.node]));

            }
        }
        viz[current.node] = true;
    }

    for(unsigned i = 0; i < dist.size(); i++)
        dist[i] = dist_u[i];



    if(dist_d[dest] != numeric_limits<int>::max())
        return true;
    else
        return false;
}

void update(int &min_cost, int start, int dest, vector <int> &parent, vector <int> &dist, vector <vector <int>> &path, vector <vector <Unit>> &flux)
{
    int current;
    int min_flux = numeric_limits<int>::max();

    for(current = dest; current != start; current = parent[current])
    {
        min_flux = min(min_flux, flux[parent[current]][current].cap);
    }

    for(current = dest; current != start; current = parent[current])
    {
        flux[parent[current]][current].cap -= min_flux;
        flux[current][parent[current]].cap += min_flux;
    }

    min_cost += min_flux * dist[dest];
}
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

int main()
{
    int n, m, start, dest;
    fin>>n>>m>>start>>dest;

    vector <vector <int>> path(n + 1);
    vector <vector <Unit>> flux(n + 1, vector <Unit> (n + 1, Unit(0, 0)));
    vector <int> dist(n + 1, numeric_limits<int>::max());
    vector <int> parent(n + 1);



    int x, y, f, c;
    for(; m; m--)
    {
        fin>>x>>y>>f>>c;

        path[x].push_back(y);
        flux[x][y] = Unit(f, c);
        path[y].push_back(x);
        flux[y][x] = Unit(0, -c);
    }

    bellman(start, dest, dist, path, flux);

    int min_cost = 0;

    while(dijkstra(start, dest, parent, dist, path, flux))
    {
        update(min_cost, start, dest, parent, dist, path, flux);
    }


    fout<<min_cost<<'\n';


    return 0;
}