Cod sursa(job #2288063)

Utilizator LucaSeriSeritan Luca LucaSeri Data 22 noiembrie 2018 20:25:41
Problema Flux maxim de cost minim Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.28 kb
#include <bits/stdc++.h>
using namespace std;

#define mp make_pair
#define sz(x) (int)((x).size())
#define all(x) (x).begin(),(x).end()
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}

typedef pair< int, int > pii;
typedef pair< long long, long long > pll;
typedef long long ll;
typedef vector< int > vi;
typedef vector< ll > vll;
typedef vector< pii > vpii;
typedef vector< pll > vpll;
typedef long double ld;
typedef vector< ld > vld;

const ll MOD = 1e9 + 7;

ll lgput(ll a, ll b, ll mod) {
    ll ret = 1;
    while( b ){
        if(b & 1) ret = (ret * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }

    return ret;
}

inline ll inv(ll x, ll MOD) {
    return lgput(x, MOD - 2, MOD);
}

const ld PI = acos(-1);
const ld eps = 1e-6;

const int MAXN = 400;

int d[MAXN];
int p[MAXN];
int cap[MAXN][MAXN];
int cost[MAXN][MAXN];
int cur[MAXN][MAXN];
int t[MAXN];

class cmp {
public:
    const bool operator() (const pii &a, const pii& b) const {
        return a.second > b.second;
    }
};

priority_queue< pii, vector< pii >, cmp > pq;
vector< int > gr[MAXN];

bool add(int source, int sink) {
    memset(d, 0x3f, sizeof d);
    memset(t, -1, sizeof t);

    d[source] = 0;

    pq.push(mp(source, 0));
    while(pq.size()) {
        int node, curCost;
        tie(node, curCost) = pq.top();
        pq.pop();
        if(curCost != d[node]) continue;

        for(auto &x : gr[node]) {
            if(cur[node][x] < cap[node][x] && curCost + cost[node][x] + p[node] - p[x] < d[x]) {
                d[x] = curCost + cost[node][x] + p[x] - p[node];
                t[x] = node;
                pq.push(mp(x, d[x]));
            }
        }
    }

    memcpy(p, d, sizeof p);
    return t[sink] != -1;
}

int viz[MAXN];
void bf(int source, int target, int n){
    memset(p, 0x3f, sizeof p);
    memset(viz, 0, sizeof viz);
    p[source] = 0;
 
    queue< int > Q;
 
    Q.push(source);
    viz[source] = true;
    while(Q.size()){
        int node = Q.front();
        viz[node] = false;
        Q.pop();
        for(auto x : gr[node]){
            if(cap[node][x] > cur[node][x] && p[x] > p[node] + cost[node][x]){
                p[x] = p[node] + cost[node][x];
                if(viz[x]) continue;
 
                viz[x] = true;
                Q.push(x);
            }
        }
    }
}

int main() {
    #ifndef ONLINE_JUDGE
         // freopen("input", "r", stdin);
    #else 
    #endif
    
     FO(fmcm);
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(20);
    cout.fixed;

    int n, m, source, sink;
    cin >> n >> m >> source >> sink;

    for(int i = 1; i <= m; ++i) {
        int a, b;
        cin >> a >> b;
        cin >> cap[a][b];
        cin >> cost[a][b];
        gr[a].emplace_back(b);
        cost[b][a] = -cost[a][b];
    }


    int ans1 = 0, ans2 = 0;
    bf(source, sink, n);
    while(add(source, sink)) {
        int node = sink;
        int minim = 1e9;
        while(node != source) {
            minim = min(minim, cap[t[node]][node] - cur[t[node]][node]);
            node = t[node];
        }

        ans1 += minim;
        node = sink;
        while(node != source) {
            ans2 += minim*(cost[t[node]][node]);
            cur[t[node]][node] += minim;
            node = t[node];
        }
    }

    cout << ans2 << '\n';
    return 0;
}