Cod sursa(job #571265)

Utilizator tamas_iuliaTamas Iulia tamas_iulia Data 4 aprilie 2011 11:05:42
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3 kb
#include <stdio.h>
#include <vector>
#include <queue>
#define Nmax 355
#define INF 2147000000
#define pb push_back
using namespace std;

vector<int> v[Nmax];
queue< int > Q;
int F[Nmax][Nmax],C[Nmax][Nmax],Cost[Nmax][Nmax];
int H[Nmax],poz[Nmax],dist[Nmax],prev[Nmax],inq[Nmax];
int N,M,S,D,sum,ok,flow,dh;

inline int Minim(int x,int y){ return x<y ? x:y ; }

inline void bf(){
    vector< int >:: iterator it;
    int i,x;
    for(i=1;i<=N;++i) dist[i]=INF;
    dist[S]=0;
    Q.push(S); inq[S]=1;

    while( !Q.empty() ){
        x=Q.front(); Q.pop();
        inq[x]=0;
        if( x==D ) continue;

        for(it=v[x].begin(); it!=v[x].end(); ++it)
            if( C[x][*it]>F[x][*it] && dist[*it]>dist[x]+Cost[x][*it] ){
                dist[*it]=dist[x]+Cost[x][*it];
                if( !inq[*it] ){
                    inq[*it]=1;
                    Q.push(*it);
                }
            }
    }
    sum = dist[D];
}

inline void swap(int i,int j){
    int aux=H[i]; H[i]=H[j]; H[j]=aux;
    poz[H[i]]=i;
    poz[H[j]]=j;
}
inline void Up(int k){
    while( k/2 && dist[H[k/2]] > dist[H[k]] ){
        swap(k,k/2);
        k/=2;
    }
}
inline void Down(int k){
    int mn=0;
    while( mn != k ){
        mn=k;
        if( 2*mn<=dh && dist[H[2*mn]] < dist[H[k]] ) k=2*mn;
        if( 2*mn+1<=dh && dist[H[2*mn+1]] < dist[H[k]] ) k=2*mn+1;
        swap(k,mn);
    }
}

inline void solve(){
    vector< int >:: iterator it;
    int i,pmin,fmin,wh,inf;

    for(i=1;i<=N;++i)
        if( dist[i] != INF )
            for(it=v[i].begin(); it!=v[i].end(); ++it)
                if( dist[*it] != INF )
                    Cost[i][*it] += dist[i] - dist[*it];

    for(i=1;i<=N;++i) dist[i]=INF,H[i]=poz[i]=i,prev[i]=0;
    dist[S]=0; dh=N;
    Up(S);

    while( dh && dist[H[1]] != INF ){
        pmin=H[1];
        swap(1,dh);
        dh--;
        Down(1);

        for(it=v[pmin].begin(); it!=v[pmin].end(); ++it)
            if( C[pmin][*it]>F[pmin][*it] && dist[*it]>dist[pmin]+Cost[pmin][*it]){
                dist[*it]=dist[pmin]+Cost[pmin][*it];
                Up(poz[*it]);
                prev[*it]=pmin;
            }
    }

    if( dist[D] != INF ){
        fmin=INF;

        for(wh=D; wh!=S; wh=prev[wh] )
            fmin=Minim(fmin,C[prev[wh]][wh]-F[prev[wh]][wh]);

        for(wh=D; wh!=S; wh=prev[wh]){
            F[prev[wh]][wh] += fmin;
            F[wh][prev[wh]] -= fmin;
        }

        sum+=dist[D];
        flow += sum*fmin;
        ok=1;
    }
}


int main(){
    int i,x,y,z,c;
    freopen("fmcm.in","r",stdin);
    freopen("fmcm.out","w",stdout);
    scanf("%d%d%d%d",&N,&M,&S,&D);
    for(i=1;i<=M;++i){
        scanf("%d%d%d%d",&x,&y,&c,&z);
        C[x][y]=c; C[y][x]=0;
        Cost[x][y]=z; Cost[y][x]=-z;
        v[x].pb(y); v[y].pb(x);
    }

    bf();

    for(ok=1; ok; ){
        ok=0;
        solve();
    }

    printf("%d\n",flow);
    fclose(stdin); fclose(stdout);
    return 0;
}