Cod sursa(job #761144)

Utilizator Theorytheo .c Theory Data 24 iunie 2012 22:36:58
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.54 kb
#include<fstream>
#include<vector>
#include<queue>

using namespace std;

#define nmax 360
#define foreach(V) for(vector<int> :: iterator it = V.begin(); it != V.end(); it++)
#define ll long long
#define min(a,b) (a>b ? b : a)

const int inf  = 1<<30;

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

int N, M, C[nmax][nmax];//capacitate
int TT[nmax], cost[nmax][nmax], dist[nmax], S, D, sum, drum ;
int F[nmax][nmax];
vector<int> G[nmax];
int H[nmax], P[nmax], L;

void push(int x)
{
    int aux;
    while(x/2 > 1 &&dist[H[x]] < dist[H[x/2]])
    {

        aux = H[x]; H[x] = H[x/2]; H[x/2] = aux;

        P[H[x/2]]= x/2;
        P[H[x]] = x;

        x/=2;
    }

}

void pop(int x)
{

    int y = 0, aux = 0;

    while(x != y)
    {
        y = x;
        if(y * 2 <= L && dist[H[x]] > dist[H[y * 2]]) x = y * 2;

        if(y * 2 + 1 <=L && dist[H[x]] > dist[H[y*2 + 1]] ) x = y * 2 + 1;

        aux =  H[x] ;   H[x] = H[y] ; H[y] = aux;

        P[H[x]] = x;
        P[H[y]] = y;

    }
}
void BellmanFord()
{
    queue <int> q;

    for(int i = 1; i <= N; i++)
        dist[i] = inf;

    dist[S] = 0;
    q.push(S);

    while( !q.empty() )
    {
        int nod = q.front();
        q.pop();
        foreach(G[nod])
        {
            int y = (*it);
            if(dist[nod] + cost[nod][y] < dist[y] && C[nod][y] > 0)
            {
                dist[y] = cost[nod][y] + dist[nod];
                q.push(y);
            }
        }
    }
    //for(int i = 1; i <= N ;i++)
     //   fout <<dist[i] <<" " ;
    sum = dist[D];//costul cel mai bun de la sursa la destinatie


}



int Dijkstra()
{

    //Fac transformarile astfel incat sa am doar costuri pozitive pe arcekle active (capcitate> flux)
    for(int i = 1; i <= N ;i++)
        foreach(G[i])
            if(dist[i] != inf && dist[*it] != inf)
                cost[i][*it] += dist[i] - dist[*it];

    for(int i = 1; i <= N; i++)
    {
        dist[i] = inf;
        TT[i] = -1;
        H[i] = i;
        P[i] = i;

    }
    dist[S] = 0 ;
    H[1] = S; H[S] = 1;
    P[1] = S; P[S] = 1;

    L = N;
    while(L>1 && dist[H[1]] !=inf)
    {
        int x  = H[1];
        foreach(G[x])
        {
            int v = *it;
            if(C[x][v] - F[x][v] > 0 && dist[x] + cost[x][v] < dist[v])
            {
                dist[v] = dist[x] + cost[x][v];
                TT[v] = H[1];
                push(P[v]);
            }
        }
        H[1] = H[L--];
        P[H[1]] = 1;
        if(L>1) pop(1);
    }
    //fout << dist[D] <<'\n';

   if(dist[D] != inf)
   {
        int vmin = inf;
       drum = 1;

       for(int i = D; i != S; i = TT[i])
       vmin = min(vmin, C[TT[i]][i] - F[TT[i]][i]);

        for(int i = D;  i != S; i = TT[i])
        {
            F[TT[i]][i] += vmin;
            F[i][TT[i]] -= vmin;
        }
     //   fout <<vmin <<'\n';
      sum+=dist[D];
      return vmin * sum;
   }
   return 0;

}
ll det_flux()
{
    ll rez = 0;
    drum = 1;

    while(drum)
    {
        drum = 0;
        rez += Dijkstra();
    }

    return rez;


}
void read()
{
    int x, y, z, cap;
    fin >>N>> M;
    fin>> S>> D;
    for(int i = 1; i <= M;i++)
    {
        fin >>x >> y>>cap>>z;
        G[x].push_back(y);
        G[y].push_back(x);
        cost[x][y] = z;
        cost[y][x] = -z;
        C[x][y] = cap;
    }
}

int main()
{
    read();
    BellmanFord();
    fout << det_flux();

    fin.close();
    return 0;

}