Cod sursa(job #962024)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 13 iunie 2013 17:37:40
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.19 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

const int oo = 0x3f3f3f3f;
const int NIL = -1;

class Edge {
  public:
    int u, v, cost, capacity, flow;

    Edge() {}

    Edge(const int u, const int v, const int cost, const int capacity) {
        this->u = u;
        this->v = v;
        this->cost = cost;
        this->capacity = capacity;
        this->flow = 0;
    }
};

vector<vector<int>> G;
vector<Edge> Edges;
int V, E, Source, Sink;
vector<int> Father, Distance;
queue<int> Q;
vector<bool> InQ;
int Solution;

inline int NonEdge(const int e) {
    if (e < E)
        return e + E;
    return e - E;
}

void InitializeBellmanFord(const int start) {
    Father = vector<int>(V, NIL);
    Distance = vector<int>(V, oo);
    InQ = vector<bool>(V, false);
    Distance[start] = 0;
    Q.push(start);
    InQ[start] = true;
}

bool BellmanFord(const int start, const int end) {
    for (InitializeBellmanFord(start); !Q.empty(); Q.pop()) {
        int x = Q.front();
        InQ[x] = false;
        if (x == end)
            continue;
        for (auto &e: G[x]) {
            int y = Edges[e].v;
            if (Edges[e].flow < Edges[e].capacity && Distance[x] + Edges[e].cost < Distance[y]) {
                Father[y] = e;
                Distance[y] = Distance[x] + Edges[e].cost;
                if (!InQ[y]) {
                    Q.push(y);
                    InQ[y] = true;
                }
            }
        }
    }
    return (Father[end] != NIL);
}

void InitializeNetwork(const int source, const int sink) {
    Source = source;
    Sink = sink;
    for (int i = 0; i < E; ++i) {
        Edges.push_back(Edge(Edges[i].v, Edges[i].u, -Edges[i].cost, 0));
        G[Edges[i].v].push_back(NonEdge(i));
    }
}

void MinCostMaxFlow(int &maxFlow, int &flowCost) {
    maxFlow = flowCost = 0;
    while (BellmanFord(Source, Sink)) {
        int flow = oo;
        for (int x = Sink; x != Source; x = Edges[Father[x]].u)
            flow = min(flow, Edges[Father[x]].capacity - Edges[Father[x]].flow);
        for (int x = Sink; x != Source; x = Edges[Father[x]].u) {
            Edges[Father[x]].flow += flow;
            Edges[NonEdge(Father[x])].flow -= flow;
        }
        maxFlow += flow;
        flowCost += flow * Distance[Sink];
    }
}

void Solve() {
    int maxFlow, flowCost;
    MinCostMaxFlow(maxFlow, flowCost);
    Solution = flowCost;
}

inline void AddEdge(const int u, const int v, const int cost, const int capacity) {
    Edges.push_back(Edge(u, v, cost, capacity));
    G[u].push_back(E++);
}

void Read() {
    ifstream in("fmcm.in");
    int edges, source, sink;
    in >> V >> edges >> source >> sink;
    G = vector<vector<int>>(V, vector<int>());
    for (; edges > 0; --edges) {
        int u, v, cost, capacity;
        in >> u >> v >> capacity >> cost;
        AddEdge(u - 1, v - 1, cost, capacity);
    }
    InitializeNetwork(source - 1, sink - 1);
    in.close();
}

void Print() {
    ofstream out("fmcm.out");
    out << Solution << "\n";
    out.close();
}

int main() {
    Read();
    Solve();
    Print();
    return 0;
}