Cod sursa(job #2962459)

Utilizator tudorcomanTudor Coman tudorcoman Data 8 ianuarie 2023 16:54:45
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.7 kb

#include <fstream>
#include <queue>

using namespace std;

const int maxN = 1001; 
const int infi = 1 << 30;

struct Muchie {
    int src, dest;
    int flx, cap; 
    int cost;
    Muchie (int _src = 0, int _dest = 0, int _flx = 0, int _cap = 0, int _cost = 0):
        src(_src), dest(_dest), flx(_flx), cap(_cap), cost(_cost) { }
} father[maxN];

vector<Muchie> G[maxN];
int cost[maxN];

bool viz[maxN];

bool bfs(int N) {
    for (int i = 1; i <= N; i ++) {
        cost[i] = infi;
        father[i] = Muchie();
    }
    queue<int> q;
    cost[1] = 0; q.push(1);
    while(!q.empty()) {
        int top = q.front(); q.pop();
        for (auto it: G[top]) {
            if (cost[top] + 1 < cost[it.dest] && it.flx < it.cap) {
                cost[it.dest] = cost[top] + 1;
                father[it.dest] = it; 
                q.push(it.dest); 
            }
        }
    }
    return cost[N] != infi; 
}

void dfs(int src) {
    viz[src] = true;
    for (auto it: G[src])
        if (it.cap - it.flx > 0 && !viz[it.dest])
            dfs(it.dest);
}

int bellman_dist[maxN], dijsktra_dist[maxN]; 

bool dijkstra(int N, int S, int D) {
    for (int i = 0; i <= N; i ++) {
        cost[i] = infi;
        father[i] = Muchie();
    }

    priority_queue< pair<int, int> > q;
    cost[S] = 0; q.push(make_pair(0, S));

    while(!q.empty()) {
        int top = q.top().second, c = -q.top().first; q.pop();

        if (cost[top] != c)
            continue;
        
        for (auto it: G[top]) {
            int dist = cost[top] + it.cost;
            dist = dist + bellman_dist[top] - bellman_dist[it.dest];

            if (dist < cost[it.dest] && it.flx < it.cap) {
                cost[it.dest] = dist;
                dijsktra_dist[it.dest] = dijsktra_dist[top] + it.cost;
                father[it.dest] = it; 
                q.push(make_pair(-cost[it.dest], it.dest)); 
            }
            
        }
    }

    for (int i = 1; i <= N; i ++)
        bellman_dist[i] = dijsktra_dist[i];

    return cost[D] != infi;
}


int main() {
    ifstream in("fmcm.in");
    ofstream out("fmcm.out");
    int N, M, S, D;
    in >> N >> M >> S >> D; 

    for (int i = 1; i <= M; i ++) {
        int src, dest, cap, cost;
        in >> src >> dest >> cap >> cost;
        G[src].push_back(Muchie(src, dest, 0, cap, cost));
        G[dest].push_back(Muchie(dest, src, 0, 0, -cost));
    }

    for (int i = 0; i <= N; i ++)
        bellman_dist[i] = infi;

    queue<int> q; 
    bellman_dist[S] = 0; q.push(S);
    viz[S] = true;
    while(!q.empty()) {
        int top = q.front(); q.pop();
        viz[top] = false;
        for (auto it: G[top]) {
            if (it.cap > 0 && bellman_dist[top] + it.cost < bellman_dist[it.dest]) {
                bellman_dist[it.dest] = bellman_dist[top] + it.cost;
                if(!viz[it.dest]) {
                    q.push(it.dest);
                    viz[it.dest] = true;
                }
            }
        }
    }


    vector<Muchie> drum;
    int flx_max = 0;
    while(dijkstra(N, S, D)) {
        int flux = infi, cost_flux = 0; 
        int x = D; 
        while (x != S) {
            flux = min(flux, father[x].cap - father[x].flx);
            cost_flux += father[x].cost;
            x = father[x].src;
        }
        flx_max += flux * cost_flux;

        x = D;
        while (x != S) {
            for (auto &it: G[father[x].src])
                if (it.dest == x) {
                    it.flx += flux;
                    break;
                }
            for (auto &it: G[father[x].dest])
                if (it.dest == father[x].src) {
                    it.flx -= flux;
                    break;
                }
            x = father[x].src;
        }
    }

    out << flx_max << "\n";
    return 0;
}