Cod sursa(job #2197489)

Utilizator andreiudilaUdila Andrei andreiudila Data 22 aprilie 2018 13:02:18
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.62 kb
#include <fstream>
#include <vector>
#include <cstring>
using namespace std;
ifstream cin("fmcm.in");
ofstream cout("fmcm.out");

vector<int> v[400];
int cap[400][400];
int cost[400][400],t[400],dmin[400];
int h[400],hsize,newd[400],idx[400],aux[400];
int q[130000],viz[400];
int x,y,c,z,n,m,s,d,i,j,flux,costf;
int inf = 2000000;
int cmin = inf;

bool drum_minim(int s, int d)
{
    memset(viz,0,sizeof(viz));
    viz[s]=1;
    int st = 1,en=1;
    q[st] = s;
    t[s]=-1;
    dmin[s]=0;
    for(int i=1; i<=n; ++i)
        if(i!=s)
            dmin[i]=inf;

    while(st<=en)
    {
        int nod = q[st];
        ++st;
        viz[nod]=0;

        for(int i=0; i<v[nod].size(); ++i)
        {
            if(cap[nod][v[nod][i]] > 0
                    && dmin[nod] + cost[nod][v[nod][i]] < dmin[v[nod][i]])
            {
                dmin[v[nod][i]] = dmin[nod] + cost[nod][v[nod][i]];
                if(!viz[v[nod][i]])
                {
                    ++en;
                    q[en]=v[nod][i];
                    viz[v[nod][i]]=1;
                }
                t[v[nod][i]] = nod;
            }
        }
    }

    if(dmin[d] != inf) return 1;
    return 0;
}

void downh()
{
    int aux=1;

    while(aux*2<=hsize)
    {
        int index=aux;

        if(newd[h[2*aux]]<newd[h[aux]]) index=2*aux;
        if(2*aux+1<=hsize)
            if(newd[h[2*aux+1]]<newd[h[index]]) index=2*aux+1;

        if(index==aux) break;

        swap(idx[h[aux]],idx[h[index]]);
        swap(h[aux],h[index]);

        aux=index;

    }

}
void uph(int x)
{
    while(x>1 && newd[h[x/2]]>newd[h[x]])
    {
        swap(idx[h[x]],idx[h[x/2]]);
        swap(h[x/2], h[x]);
        x/=2;
    }
}

bool exista_drum(int s, int d)
{
    //memset(aux,0,sizeof(aux));
    memset(t,0,sizeof(t));
    aux[s]=0;

    t[s]=-1;

    for(int i=1; i<=n; ++i)
    {
        h[i]=i;
        idx[i]=i;
        newd[i]=inf;
    }


    newd[s]=0;

    h[1]=s;
    h[s]=1;
    idx[s]=1;
    idx[1]=s;

    hsize=n;
    while(hsize>0)
    {
        int nodc=h[1];
        idx[h[hsize]]=1;
        h[1]=h[hsize];
        --hsize;
        downh();
        if(t[nodc]==0) continue;
        int costm = 0;
        for(int i=0; i<v[nodc].size(); ++i)
        {
            if(cap[nodc][v[nodc][i]] > 0)
            {
                costm =dmin[nodc] + cost[nodc][v[nodc][i]] - dmin[v[nodc][i]] ;
                if(newd [v[nodc][i]] > newd[nodc] + costm)
                {
                    newd[v[nodc][i]] = newd[nodc] + costm;
                    t[v[nodc][i]] = nodc;
                    uph(idx[v[nodc][i]]);
                    aux[v[nodc][i]] = aux[nodc] + cost[nodc][v[nodc][i]];
                }
            }
        }

    }

    return t[d]!=0;
}
int main()
{
    cin>>n>>m>>s>>d;
    for(i=1; i<=m; ++i)
    {
        cin>>x>>y>>c>>z;
        v[x].push_back(y);
        cap[x][y]=c;
        cost[x][y]=z;
        v[y].push_back(x);
        cap[y][x]=0;
        cost[y][x]=-z;
    }

    drum_minim(s,d);

    int nod = d;
    while(exista_drum(s,d))
    {
        for(i=1; i<=n; ++i)
            dmin[i]=aux[i];

        nod = d;
        cmin = inf;
        while(nod != s)
        {
            cmin = min(cmin,cap[t[nod]][nod]);
            nod = t[nod];
        }

        flux += cmin;
        costf += dmin[d]*cmin;

        nod = d;
        while(nod !=s)
        {
            cap[nod][t[nod]] += cmin;
            cap[t[nod]][nod] -= cmin;
            nod = t[nod];
        }

    }

    cout<<costf;
    return 0;
}