Cod sursa(job #1655419)

Utilizator alexpetrescuAlexandru Petrescu alexpetrescu Data 17 martie 2016 22:59:59
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.48 kb
#include <cstdio>
#define INF 1000000000
#define MAXN 350
#define MAXM 12500
#define MASK 511
int s, u, n, k;
int heap[MAXN+1], poz[MAXN+1], val[2*MAXM+1], next[2*MAXM+1], lista[MAXN+1], from[MAXN+1], dist[MAXN+1];
int cost[MAXN+1][MAXN+1], c[MAXN+1][MAXN+1], f[MAXN+1][MAXN+1], d[MAXN+1], q[MASK+1], real[MAXN+1];
bool ok[MAXN+1];
inline int tata(int p){
    return p/2;
}
inline int fiust(int p){
    return 2*p;
}
inline int fiudr(int p){
    return 2*p+1;
}
inline void swap(int p, int q){
    int aux=heap[p];
    heap[p]=heap[q];
    heap[q]=aux;
    poz[heap[p]]=p;
    poz[heap[q]]=q;
}
inline void urcare(int p){
    while((p>1)&&(d[heap[p]]<d[heap[tata(p)]])){
        swap(p, tata(p));
        p=tata(p);
    }
}
inline void coborare(int p){
    int q, f=1;
    while((f)&&(fiust(p)<=n)){
        q=fiust(p);
        if((fiudr(p)<=n)&&(d[heap[fiudr(p)]]<d[heap[q]])){
            q=fiudr(p);
        }
        if(d[heap[q]]<d[heap[p]]){
            swap(p, q);
            p=q;
        }else{
            f=0;
        }
    }
}
inline bool dijkstra(){
    int i, p, x;
    for(i=1; i<=n; i++){
        d[i]=INF;
        heap[i]=i;
        poz[i]=i;
        ok[i]=0;
    }
    real[s]=0;
    d[s]=0;
    urcare(poz[s]);
    while(d[heap[1]]!=INF){
        x=heap[1];
        ok[x]=1;
        p=lista[x];
        while(p){
            if((c[x][val[p]]>f[x][val[p]])&&(ok[val[p]]==0)&&(d[val[p]]>d[x]+cost[x][val[p]]+dist[x]-dist[val[p]])){
                d[val[p]]=d[x]+cost[x][val[p]]+dist[x]-dist[val[p]];
                real[val[p]]=real[x]+cost[x][val[p]];
                from[val[p]]=x;
                urcare(poz[val[p]]);
            }
            p=next[p];
        }
        d[x]=INF;
        coborare(poz[x]);
    }
    for(i=1; i<=n; i++){
        dist[i]=real[i];
    }
    return ok[u];
}
inline void bellmanFord(){
    int st, dr, i, p, x;
    for(i=1; i<=n; i++){
        dist[i]=INF;
    }
    q[0]=s;
    st=0;
    dr=1;
    dist[s]=0;
    ok[s]=1;
    while(st<dr){
        x=q[st&MASK];
        st++;
        ok[x]=0;
        p=lista[x];
        while(p){
            if((dist[val[p]]>dist[x]+cost[x][val[p]])&&(c[x][val[p]])){
                dist[val[p]]=dist[x]+cost[x][val[p]];
                if(ok[val[p]]==0){
                    ok[val[p]]=1;
                    q[dr&MASK]=val[p];
                    dr++;
                }
            }
            p=next[p];
        }
    }
}
inline void adauga(int x, int y, int z, int t){
    k++;
    val[k]=y;
    c[x][y]+=z;
    cost[x][y]+=t;
    next[k]=lista[x];
    lista[x]=k;
}
int main(){
    int ans, rez, min, m, x, y, z, t, i;
    FILE *fin, *fout;
    fin=fopen("fmcm.in", "r");
    fout=fopen("fmcm.out", "w");
    fscanf(fin, "%d%d%d%d", &n, &m, &s, &u);
    for(i=1; i<=m; i++){
        fscanf(fin, "%d%d%d%d", &x, &y, &z, &t);
        adauga(x, y, z, t);
        adauga(y, x, 0, -t);
    }
    bellmanFord();
    rez=0;
    ans=0;
    while(dijkstra()){
        min=INF;
        x=u;
        while(x!=s){
            if(min>c[from[x]][x]-f[from[x]][x]){
                min=c[from[x]][x]-f[from[x]][x];
            }
            x=from[x];
        }
        rez+=min;
        ans+=min*real[u];
        x=u;
        while(x!=s){
            f[from[x]][x]+=min;
            f[x][from[x]]-=min;
            x=from[x];
        }
    }
    fprintf(fout, "%d\n", ans);
    fclose(fin);
    fclose(fout);
    return 0;
}