Cod sursa(job #873116)

Utilizator sleepaholicNeculaescu Theodor sleepaholic Data 6 februarie 2013 21:30:11
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.45 kb
// Include
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

// Definitii
#define pb push_back
#define mp make_pair

#define edge pair<int, int>
#define edgeCost first
#define edgeNode second

// Constante
const int sz = 351;
const int oo = (1<<30)-1;

// Functii
void bellmanFord();
bool dijkstra();

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

bool inQueue[sz];

int nodes, edges;
int source, destination;
int minFlowMaxCost;
int father[sz], dist[sz], realDist[sz], oldDist[sz];
int capacity[sz][sz], flow[sz][sz], cost[sz][sz];

vector<int> graph[sz];

// Main
int main()
{
    in >> nodes >> edges >> source >> destination;

    int rFrom, rTo, rCapacity, rCost;
    while(edges--)
    {
        in >> rFrom >> rTo >> rCapacity >> rCost;
        graph[rFrom].pb(rTo);
        graph[rTo].pb(rFrom);

        capacity[rFrom][rTo] = rCapacity;

        cost[rFrom][rTo] = rCost;
        cost[rTo][rFrom] = -rCost;
    }

    bellmanFord();

    while(dijkstra())
    {
        int minFlow = oo;

        for(int node=destination ; node!=source ; node=father[node])
            minFlow = min(minFlow, capacity[father[node]][node] - flow[father[node]][node]);

        for(int node=destination ; node!=source ; node=father[node])
        {
            flow[father[node]][node] += minFlow;
            flow[node][father[node]] -= minFlow;
        }

        minFlowMaxCost += minFlow * realDist[destination];
    }

    out << minFlowMaxCost << '\n';

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

void bellmanFord()
{
    for(int i=1 ; i<=nodes ; ++i)
        oldDist[i] = oo;

    queue<int> q;

    q.push(source);
    inQueue[source] = true;
    oldDist[source] = 0;

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

        vector<int>::iterator it, end=graph[current].end();

        for(it=graph[current].begin() ; it!=end ; ++it)
        {
            if(capacity[current][*it] && oldDist[current]+cost[current][*it] < oldDist[*it])
            {
                oldDist[*it] = oldDist[current]+cost[current][*it];
                if(!inQueue[*it])
                    q.push(*it), inQueue[*it] = true;
            }
        }
        inQueue[current] = false;
    }
}

bool dijkstra()
{
    for(int i=1 ; i<=nodes ; ++i)
        dist[i] = oo, father[i] = 0;

    priority_queue<edge, vector<edge>, greater<edge> > heap;

    dist[source] = 0;
    heap.push(mp(0, source));

    while(!heap.empty())
    {
        int current=heap.top().edgeNode;
        if(heap.top().edgeCost != dist[current])
        {
            heap.pop();
            continue;
        }
        heap.pop();
        vector<int>::iterator it, end = graph[current].end();
        for(it=graph[current].begin() ; it!=end ; ++it)
        {
            if(capacity[current][*it] != flow[current][*it] &&
            dist[current] + cost[current][*it] + oldDist[current] - oldDist[*it] < dist[*it])
            {
                dist[*it] = dist[current] + cost[current][*it] + oldDist[current] - oldDist[*it];
                father[*it] = current;
                realDist[*it] = realDist[current] + cost[current][*it];
                heap.push(mp(dist[*it], *it));
            }
        }
    }

    for(int i=1 ; i<=nodes ; ++i)
        oldDist[i] = realDist[i];

    return father[destination]? 1:0;
}