Cod sursa(job #2374683)

Utilizator Tataru_AdelinTataru Adelin Tataru_Adelin Data 7 martie 2019 19:57:54
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.12 kb
#include <bits/stdc++.h>

using namespace std;


class Edge
{
public:
    int node;
    int cost;

    Edge()
    {}

    Edge(int n, int c)
    {
        node = n;
        cost = c;
    }

};

class Unit
{
public:
    int cap;
    int cost;

    Unit()
    {}

    Unit(int f, int c)
    {
        cap = f;
        cost = c;
    }
};

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

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

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

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

void Bellman(int start, vector <vector <Edge>> &path, vector <vector <Unit>> &flux, vector <int> &dist, vector <bool> &vis)
{
    reset(vis);
    vector_set(dist, numeric_limits<int>::max());

    queue <int> q;

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

    int now;
    Edge vec;

    while(!q.empty())
    {
        now = q.front();
        q.pop();
        vis[now] = false;

        for(unsigned i = 0; i < path[now].size(); i++)
        {
            vec = path[now][i];
            if(flux[now][vec.node].cap > 0 && dist[vec.node] > dist[now] + vec.cost)
            {
                dist[vec.node] = dist[now] + vec.cost;

                if(!vis[vec.node])
                {
                    q.push(vec.node);
                    vis[vec.node] = true;
                }
            }
        }
    }
}

bool Dijkstra(int start, int dest, vector <vector <Edge>> &path, vector <vector <Unit>> &flux, vector <int> &parent, vector <int> &dist, vector <bool> &vis)
{
    vector <int> dist_d(path.size(), numeric_limits<int>::max());
    vector <int> dist_u(path.size(), numeric_limits<int>::max());

    reset(parent);
    reset(vis);

    priority_queue <Edge, vector <Edge>, Comp> q;

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

    int now;
    Edge vec;

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

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

                parent[vec.node] = now;

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

        vis[now] = true;
    }

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

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

void Update(int start, int dest, int &ans, vector <vector <Edge>> &path, vector <vector <Unit>> &flux, vector <int> &dist, vector <int> &parent)
{
    int max_flux = numeric_limits<int>::max();

    for(int now = parent[dest], vec = dest; vec != start; vec = now, now = parent[now])
    {
        max_flux = min(max_flux, flux[now][vec].cap);
    }

    for(int now = parent[dest], vec = dest; vec != start; vec = now, now = parent[now])
    {
        flux[now][vec].cap -= max_flux;
        flux[vec][now].cap += max_flux;
    }

    ans += dist[dest] * max_flux;
}

ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

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

    vector <vector <Edge>> path(n + 1);
    vector <vector <Unit>> flux(n + 1, vector <Unit> (n + 1, Unit(0, 0)));

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

        path[x].push_back(Edge(y, c));
        path[y].push_back(Edge(x, -c));

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

    int ans = 0;
    vector <int> dist(n + 1);
    vector <int> parent(n + 1);
    vector <bool> vis(n + 1);

    Bellman(start, path, flux, dist, vis);

    while(Dijkstra(start, dest, path, flux, parent, dist, vis))
    {
        Update(start, dest, ans, path, flux, dist, parent);
    }

    fout<<ans<<'\n';

    return 0;
}