Cod sursa(job #1669196)

Utilizator tudormaximTudor Maxim tudormaxim Data 30 martie 2016 15:05:41
Problema Flux maxim de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.03 kb
#include <iostream>
#include <fstream>
#include <bitset>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

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

const int nmax = 355;
const int oo = 2e9;
vector <int> g[nmax];
int cap[nmax][nmax], cost[nmax][nmax], f[nmax][nmax], dady[nmax];
int old_dist[nmax], real_dist[nmax], dist[nmax], n, m;

void bellman(int source, int dest) {
    vector <int> :: iterator son;
    queue <int> q;
    bitset <nmax> viz;
    int dad;
    fill(old_dist+1, old_dist+n+1, oo);
    old_dist[source]=0;
    q.push(source);
    while(!q.empty()){
        dad=q.front();
        viz[dad]=false;
        q.pop();
        for(son=g[dad].begin(); son!=g[dad].end(); son++)
            if(old_dist[*son] > old_dist[dad]+cost[dad][*son] && cap[dad][*son]){
                old_dist[*son]=old_dist[dad]+cost[dad][*son];
                if(viz[*son]==false){
                    viz[*son]=true;
                    q.push(*son);
                }
            }
    }
}

bool dijkstra(int source, int dest) {
    priority_queue <pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > heap;
    vector <int> :: iterator son;
    int dad, new_dist, cst;
    fill(dist+1, dist+n+1, oo);
    fill(real_dist+1, real_dist+n+1, oo);
    dist[source]=real_dist[source]=0;
    heap.push({0, source});
    while(!heap.empty()) {
        cst=heap.top().first;
        dad=heap.top().second;
        heap.pop();
        if(cst!=dist[dad]) continue;
        for(son=g[dad].begin(); son!=g[dad].end(); son++)
            if(cap[dad][*son] > f[dad][*son]) {
                new_dist=dist[dad]+cost[dad][*son]+old_dist[dad]-old_dist[*son];
                if(real_dist[*son] > new_dist) {
                    dady[*son]=dad;
                    dist[*son]=new_dist;
                    real_dist[*son]=real_dist[dad]+cost[dad][*son];
                    heap.push({dist[*son], *son});
                }
            }

    }
    for(int i=1; i<=n; i++)
        old_dist[i]=real_dist[i];
    if(dist[dest]==oo) return false;
    return true;
}

void Max_Flow_Min_Cost(int source, int dest) {
    int max_flow=0, flow, node;
    bellman(source, dest);
    while(dijkstra(source, dest)) {
        flow=oo;
        for(node=dest; node!=source; node=dady[node]) {
            flow=min(flow, cap[dady[node]][node]-f[dady[node]][node]);
        }
        for(node=dest; node!=source; node=dady[node]) {
            f[dady[node]][node]+=flow;
            f[node][dady[node]]-=flow;
        }
        max_flow=flow*dist[dest];
    }
    fout << max_flow;
}

int main() {
    ios_base::sync_with_stdio(false);
    int x, y, c, cs, i, source, dest;
    fin >> n >> m >> source >> dest;
    for(i=1; i<=m; i++) {
        fin >> x >> y >> c >> cs;
        g[x].push_back(y);
        g[y].push_back(x);
        cap[x][y]=c;
        cost[x][y]=cs;
        cost[y][x]=-cs;
    }
    Max_Flow_Min_Cost(source, dest);
    fin.close();
    fout.close();
    return 0;
}