Cod sursa(job #1439240)

Utilizator ELHoriaHoria Cretescu ELHoria Data 21 mai 2015 21:00:51
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.12 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <functional>
#include <cstring>
#include <queue>
#include <limits> 

using namespace std;
 
class MinCostMaxFlow {
        vector< vector<int> > dist, cap, cost, graph;
        vector<bool> inQueue;
        vector<int> T;
        int source, sink, N, distLine;
        const int inf = numeric_limits<int>::max();
    public: 

        void addEdge(int x, int y,int z, int c) {
            cost[x][y] = z;
            cost[y][x] = -z;
            graph[x].push_back(y);
            graph[y].push_back(x);
            cap[x][y] = c;
        }

        MinCostMaxFlow(int n, int s, int S) {
            N = n;
            source = s;
            sink = S;
            dist.resize(3, vector<int>(N));
            distLine = 0;
            cap.resize(N, vector<int>(N));
            cost = cap;
            graph.resize(N);
            T.resize(N);
            inQueue.resize(N);
        }

        bool bellman() {
            queue<int> Q;
            for(int i = 0;i < N;i++) {
                dist[distLine][i] = inf;
            }

            dist[distLine][source] = 0;
            Q.push(source);
            inQueue[source] = true;
            while (!Q.empty()) {
                int v = Q.front();
                Q.pop();
                inQueue[v] = false;
                for (int& w : graph[v]) {
                    if(cap[v][w] > 0 && dist[distLine][w] > dist[distLine][v] + cost[v][w]) {
                        dist[distLine][w] = dist[distLine][v] + cost[v][w];
                        if (!inQueue[w]) {
                            inQueue[w] = true;
                            Q.push(w);
                        }
                    }
                }
            } 

            if(dist[distLine][sink] == inf) {
                return false;
            }

            return true;
        }
        
        pair<int,int> djikstra() {
            distLine = 1 - distLine;
            for(int i = 0; i < N;i++) {
                dist[distLine][i] = inf;
                dist[2][i] = inf;
            }
            priority_queue< pair<int,int> > h;
            dist[distLine][source] = dist[2][source] = 0;
            h.push(make_pair(0,source)); 
            while (!h.empty()) {
                int v = h.top().second;
                int currentCost = -h.top().first;
                h.pop();
                if(currentCost != dist[2][v]) continue;
                for (int& w : graph[v]) {
                    if(cap[v][w] > 0 && dist[2][w] > dist[2][v] + cost[v][w] + dist[1 - distLine][v] - dist[1 - distLine][w]) {
                        dist[2][w] = dist[2][v] + cost[v][w] + dist[1 - distLine][v] - dist[1 - distLine][w];
                        T[w] = v;
                        dist[distLine][w] = dist[distLine][v] + cost[v][w];
                        h.push(make_pair(-dist[2][w], w));
                    }
                }
            }

            if (dist[2][sink] == inf) {
                return make_pair(0,0);
            }
            int fmin = inf;
            for (int v = sink;v != source;v = T[v]) {
                fmin = min(fmin,cap[T[v]][v]);
            }
            for (int v = sink;v != source;v = T[v]) {
                cap[T[v]][v] -= fmin;
                cap[v][T[v]] += fmin;
            }
            return make_pair(fmin,fmin*dist[distLine][sink]);
        }
         
        pair<int,int> solve() { //flow,flow cost
            pair<int,int> ret, current;
            ret.first = ret.second = 0;
            if(bellman()) {
                do {
                    current = djikstra();
                    ret.first += current.first;
                    ret.second += current.second;
                } while(current.second != 0);
            }
            return ret;
        }

};
 
int main() 
{
    ifstream cin("fmcm.in");
    ofstream cout("fmcm.out");
    int n, m, s, d, a, b, c;
    cin >> n >> m >> s >> d;
    s--, d--;
    MinCostMaxFlow solver(n, s, d);
    for (int i = 0; i < m; i++) {
        cin >> a >> b >> c >> d;
        a--, b--;
        solver.addEdge(a, b, d, c);
    }
    pair<int,int> ans = solver.solve();
    cout << ans.second;
    return 0;
}