Cod sursa(job #2582968)

Utilizator SoranaAureliaCatrina Sorana SoranaAurelia Data 17 martie 2020 16:33:12
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.2 kb
#include <fstream>
#include <cstring>
#include <bitset>
#include <vector>
#include <queue>
#include <set>

#define NMAX 360
#define oo 0x3f3f3f3f

using namespace std;

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

int n, m, s, d; // n noduri, m muchii, s sursa, d destinatia
int x, y, c, z; // arc de la x la y de capacitate c, cost z
int cap[NMAX][NMAX], flow[NMAX][NMAX], cost[NMAX][NMAX];
int dmin[NMAX]; // dist[i] = distanta de la sursa la i -> bellman ford
int dmindij[NMAX]; // distdij[i] = distanta de la sursa la i -> dijkstra !!niciun nr negativ
int tati[NMAX]; // pt a recrea drumul de cost minim
int dnealterat[NMAX]; // drum fara a lua in calcul artificiul pt pozitiv

struct muchie{
    int y, cost;
    bool operator<(const muchie &other) const{
        if(cost == other.cost)
            return y<other.y;
        return cost<other.cost;
    }
};
vector<muchie> graph[NMAX];
queue<int> Q;

void citire(){
    f>>n>>m>>s>>d;
    for(int i=1; i<=m; i++){
        f>>x>>y>>c>>z;

        graph[x].push_back({y, z});
        graph[y].push_back({x, -z}); // graf rezidual


        cap[x][y] = c;
        cost[x][y] = z;
        cost[y][x] = -z;
    }
}

void bellman_ford(){
    bitset<NMAX>viz;
    viz.reset();
    memset(dmin, oo, sizeof(dmin));

    dmin[s] = 0;
    Q.push(s);
    viz[s] = true;
    while(!Q.empty()){
        int nod = Q.front();
        Q.pop();
        for(auto v:graph[nod])
            if(cap[nod][v.y]!=flow[nod][v.y] && dmin[nod] + v.cost < dmin[v.y]){ // daca poate trece "flow"
                dmin[v.y] = dmin[nod] + v.cost;
                if(!viz[v.y])
                    Q.push(v.y);
                viz[v.y] = true;
            }
        viz[nod] = false;
    }
}

int cost_nou(int cost, int nod1, int nod2){
    return cost+dmin[nod1]-dmin[nod2];
}

bool dijkstra(){
    set<muchie> S;
    memset(dmindij, oo, sizeof(dmindij));
    dmin[s] = 0;
    dnealterat[s] = 0;
    dmindij[s] = 0;
    S.insert({s, 0}); // y = s, cu costul 0
    while(!S.empty()){
        int nod = S.begin()->y;
        S.erase(S.begin());

        for(auto v:graph[nod])
            if(dmindij[nod] + cost_nou(v.cost, nod, v.y) < dmindij[v.y] && cap[nod][v.y]!=flow[nod][v.y]){
                if(dmindij[v.y]!=oo)
                    S.erase({v.y, dmindij[v.y]});
                dmindij[v.y] = dmindij[nod] + cost_nou(v.cost, nod, v.y);;
                dnealterat[v.y] = dnealterat[nod] + v.cost;
                tati[v.y] = nod;
                S.insert({v.y, dmindij[v.y]});
            }
    }
    return dmindij[d]!=oo; // daca am ajuns la n
}

void solve(){
    int ans=0;
    while(dijkstra()){
        int maxFlow=oo;
        for(int i = d; i!=s; i=tati[i])
            maxFlow=min(maxFlow, cap[tati[i]][i] - flow[tati[i]][i]);
        if(maxFlow == 0)
            continue;
        ans += maxFlow*dnealterat[d];
        for(int i=d; i!=s; i=tati[i]){
            flow[tati[i]][i]+=maxFlow;
            flow[i][tati[i]]-=maxFlow;
        }
        for(int i=1; i<=n; i++)
            dmin[i] = dnealterat[i];
    }
    g<<ans<<" ";
}

int main()
{
    citire();
    bellman_ford();
    solve();
    return 0;
}