Cod sursa(job #2416452)

Utilizator GoogalAbabei Daniel Googal Data 27 aprilie 2019 16:20:34
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.8 kb
#include <iostream>
#include <fstream>
#include <climits>
#include <bitset>
#include <vector>
#include <queue>

using namespace std;

int const nmax = 350;
int const DIM = 10000;

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


struct Edge
{
    int to;
    int rev;
    int flow;
    int cap;
    int cost;
};

vector<Edge> g[1 + nmax];

struct Node
{
    int node;
    int d;

    bool operator> (Node other) const
    {
        return d > other.d;
    }
};

int n, m, src, dest;
int dist[1 + nmax], distdij[1 + nmax];
int prio[1 + nmax];
bitset<1 + nmax> vis;
int prevnode[1 + nmax], prevedge[1 + nmax], pushflow[1 + nmax];
char buff[DIM];
int poz;

void read(int &nr)
{
    nr = 0;
    char sgn = '+';
    while (buff[poz] < '0' || buff[poz] > '9')
    {
        sgn = buff[poz];
        if (++poz == DIM)
            in.read(buff, DIM), poz = 0;
    }

    while ('0' <= buff[poz] && buff[poz] <= '9')
    {
        nr = nr * 10 + buff[poz] - '0';
        if (++poz == DIM)
            in.read(buff, DIM), poz = 0;
    }

    if (sgn == '-')
        nr *= -1;
}

void addedge(int x, int y, int cap, int cost)
{
    Edge direct  = {y, g[y].size(), 0, cap,  cost};
    Edge inverse = {x, g[x].size(), 0,   0, -cost};
    g[x].push_back(direct);
    g[y].push_back(inverse);
}

void bellmanford()
{
    queue <int> q;

    fill(dist + 1, dist + n + 1, INT_MAX);
    dist[src] = 0;
    q.push(src);

    while(!q.empty())
    {
        int from = q.front();
        vis[from] = 0;
        q.pop();

        for(int i = 0; i < g[from].size(); i++)
        {
            Edge &e = g[from][i];
            if(e.flow < e.cap)
            {
                int to = e.to;
                int newdist = dist[from] + e.cost;
                if(newdist < dist[to])
                {
                    dist[to] = newdist;
                    if(vis[to] == 0)
                    {
                        q.push(to);
                        vis[to] = 1;
                    }
                }
            }
        }
    }
}

void dijkstra()
{
    priority_queue<Node, vector<Node>, greater<Node> > pq; //in mod corect
    distdij[src] = 0;
    pq.push({src, distdij[src]});
    vis = 0; //ai inteles de ce pot sa fac asta? Pentru ca e bitset
    pushflow[src] = INT_MAX;

    while(!pq.empty())
    {
        int from = pq.top().node;
        pq.pop();

        if(vis[from] == 0)
        {
            vis[from] = 1;
            for(int i = 0; i < g[from].size(); i++)
            {
                Edge &e = g[from][i];
                if(vis[e.to] == 0)
                {
                    int to = e.to;
                    if(e.flow < e.cap)
                    {
                        int newdistdij = distdij[from] + e.cost + dist[from] - dist[to];
                        if(newdistdij < distdij[to])
                        {
                            distdij[to] = newdistdij;
                            prevnode[to] = from;
                            prevedge[to] = i;
                            pushflow[to] = min(pushflow[from], e.cap - e.flow);
                            pq.push({to, distdij[to]});
                        }
                    }
                }
            }
        }
    }
}

void mincostflow(int &flow, int &flowcost)
{
    bellmanford();
    //cout << "BF\n";

    flow = flowcost = 0;
    while(distdij[dest] < INT_MAX)
    {
        fill(distdij + 1, distdij + n + 1, INT_MAX);
        dijkstra();
        //cout << "DJ\n";
        if(distdij[dest] < INT_MAX)
        {

            //new level graph
            for(int i = 1; i <= n; i++)
            {
                dist[i] += distdij[i];
            }

            //blocking flow
            int deltaflow = pushflow[dest];
            flow += deltaflow;
            for(int to = dest; to != src; to = prevnode[to])
            {
                Edge &e = g[prevnode[to]][prevedge[to]];
                e.flow += deltaflow;
                g[to][e.rev].flow -= deltaflow;
                flowcost += deltaflow * e.cost;
                //cout << deltaflow << ' ' << e.cost << ' ' << flowcost << '\n';
            }
        }
    }
}

int main()
{
    //in >> n >> m >> src >> dest;
    read(n);
    read(m);
    read(src);
    read(dest);
    //cout << dest << '\n';
    for(int i = 1; i <= m; i++)
    {
        int x, y, cost, cap;
        //in >> x >> y >> cap >> cost;
        read(x);
        read(y);
        read(cap);
        read(cost);
        addedge(x, y, cap, cost);
        //cout << x << ' ' << y << ' ' << cap << ' ' << cost << '\n';
    }

    int flow, flowcost;
    mincostflow(flow, flowcost);
    out << flowcost << '\n';

    in.close();
    out.close();
    return 0;
}