Cod sursa(job #993346)

Utilizator Impaler_009Mihai Nitu Impaler_009 Data 3 septembrie 2013 17:48:21
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.76 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>

#define maxn 352
#define inf 350001
#define vint vector<int>::iterator

using namespace std;

ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

//general
vector <int> G[maxn];
int C[maxn][maxn],Cost[maxn][maxn],F[maxn][maxn];
int n,m,s,d,a,b,c,z,flowcost,flow;

//for Bellman-Ford
queue <int> Q;
int D[maxn]; bool viz[maxn];

//for Dijkstra
int h[maxn],hpoz[maxn];
int path[maxn],old_d[maxn],real_d[maxn];
int hsize;

inline int father (const int &x)
{
    return x>>1;
}

inline int left_son (const int &x)
{
    return x<<1;
}

inline int right_son (const int &x)
{
    return (x<<1)+1;
}

void upheap (int poz)
{
    int pullout = h[poz];

    while (D[pullout] < D[h[father(poz)]])
    {
        h[poz] = h[father(poz)];
        hpoz[h[poz]] = poz;
        poz >>= 1;
    }

    h[poz] = pullout;
    hpoz[h[poz]] = poz;
}

void downheap (int poz)
{
    int pullout = h[poz], ok = 0;

    while (ok!=-1)
    {
        ok=-1;
        if (left_son(poz) <= hsize && D[pullout] > D[h[left_son(poz)]]) ok=0;
        if (right_son(poz) <= hsize && D[pullout] > D[h[right_son(poz)]])
        {
            if (ok==0) {if (D[h[right_son(poz)]] < D[h[left_son(poz)]]) ok=1;}
            else ok=1;
        }

        if (ok!=-1)
        {
            h[poz] = h[(poz<<1)+ok];
            hpoz[h[poz]] = poz;
            poz = (poz<<1) + ok;
        }
    }

    h[poz] = pullout;
    hpoz[h[poz]] = poz;
}

bool dijkstra ()
{
    for (int i=1; i<=n+1; ++i) D[i]=inf, viz[i]=0, h[i]=i, hpoz[i]=i;
    D[s] = 0;
    swap (h[s],h[1]);
    swap (hpoz[s],hpoz[1]);

    hsize = n;

    while (D[h[1]]!=inf)
    {
        int x = h[1];

        if (viz[x]) continue;
        viz[x]=1;

        for (vint it = G[x].begin(); it!=G[x].end(); ++it)
        {
            if (C[x][*it]==F[x][*it]) continue;

            int cst = D[x] + Cost[x][*it] + old_d[x] - old_d[*it];

            if (cst < D[*it])
            {
                D[*it] = cst;
                real_d[*it] = real_d[x] + Cost[x][*it];
                path[*it] = x;

                upheap (hpoz[*it]);
            }
        }
        h[1] = h[hsize];
        hpoz[h[1]] = 1;
        h[hsize] = n+1;
        --hsize;

        downheap (1);
    }
    return D[d]!=inf;
}

void bellman_ford ()
{
    for (int i=1; i<=n; ++i) old_d[i]=inf;
    old_d[s]=0;

    Q.push(s);
    viz[s]=1;

    while (!Q.empty())
    {
        int x = Q.front();
        for (vint it = G[x].begin(); it!=G[x].end(); ++it)
        {
            if (C[x][*it]==F[x][*it]) continue;

            if (old_d[x] + Cost[x][*it] < old_d[*it])
            {
                old_d[*it] = old_d[x] + Cost[x][*it];
                if (!viz[*it])
                {
                    viz[*it]=1;
                    Q.push(*it);
                }
            }
        }
        viz[x] = 0;
        Q.pop();
    }
}

int main()
{
    fin>>n>>m>>s>>d;

    for (int i=1; i<=m; ++i)
    {
        fin>>a>>b>>c>>z;
        C[a][b] = c;
        Cost[a][b] = z;
        Cost[b][a] = -z;
        G[a].push_back(b);
        G[b].push_back (a);
    }

    bellman_ford ();

    flowcost=0,flow=0;


    while (dijkstra())
    {
        int minf = inf;

        for (int i = d; i!=s; i=path[i])
        {
            minf = min (minf,C[path[i]][i]-F[path[i]][i]);
        }

        flow += minf;
        flowcost += minf * real_d[d];

        for (int i = d; i!=s; i=path[i])
        {
            F[path[i]][i] += minf;
            F[i][path[i]] -= minf;
        }

        memcpy (old_d, real_d, sizeof(real_d));
    }

    fout<<flowcost;

    return 0;
}