Cod sursa(job #349096)

Utilizator marcelcodreaCodrea Marcel marcelcodrea Data 17 septembrie 2009 23:56:32
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.45 kb
#include<stdio.h>
#define INF 13000000
struct Nod {
    int V;
    int C;
    int CS;
    Nod *Next;
};
struct NodHeap {
    int Val;
};
struct Muchie {
    int x;
    int y;
    int dist;
};

Nod *a[355];
int drum;
int N;
int Ds[355][355];
int Heap[200000];
int Wh[800];
long long Res;
int M;
int C[352][352];
int F[352][352];
int countDij;
int x;
int Dist[400];
int aux;
int Sum;
int y;
int countE;
int extractNod;
int PozInGraf[20000];
int PozInHeap[20000];
Muchie sir[12505];
int dimHeap;
int s,d;
int c;
int z;
void insert(Nod *&now, int nod, int capac, int cost)
{
        Nod *op = new Nod;
        op -> V = nod;
        op -> C = capac;
        op -> CS = cost;
        op -> Next = now;
        now = op;
}

void BellmanFord()
{
    for(int i = 1; i <= N; i++)
     Dist[i] = INF;
    Dist[s] = 0;
    for(int i = 1; i <= N - 1; i++)
     {
         for(int j = 1; j <= countE; j++)
          if (Dist[sir[j].y] > Dist[sir[j].x] + sir[j].dist)
           Dist[sir[j].y] = Dist[sir[j].x] + sir[j].dist;
     }
     Sum = Dist[d];


}
void Swap(int i, int j)
{
    int aux;
    aux = Heap[i];
    Heap[i] = Heap[j];
    Heap[j] = aux;
    aux = PozInGraf[i];
    PozInGraf[i] = PozInGraf[j];
    PozInGraf[j] = aux;
    aux = PozInHeap[PozInGraf[i]];
    PozInHeap[PozInGraf[i]] = PozInHeap[PozInGraf[j]];
    PozInHeap[PozInGraf[j]] = aux;

}
void HeapDown(int nod)
{
    int min = nod;
    if (2 * nod <= dimHeap)
     if (Heap[2 * nod] < Heap[min])  min = 2 * nod;
    if (2 * nod + 1 <= dimHeap)
      {
         if (Heap[2 * nod] < Heap[min])  min = 2 * nod;
         if (Heap[2 * nod + 1] < Heap[min])  min = 2 * nod + 1;
      }
     if (min != nod)
      {
          Swap(min,nod);
          HeapDown(min);
      }

}
void Modifica()
{
    for(int i = 1; i <= N; i++)
     for(Nod *it = a[i]; it; it = it -> Next)
      if (Dist[i] != INF && Dist[it->V]  != INF)
     {
      it -> CS = it -> CS + Dist[i] - Dist[it->V];
      Ds[i][it->V] = it->CS;
     }
}
int ExtractMin()
{
    Swap(1,dimHeap);
    dimHeap--;
    HeapDown(1);

    return PozInGraf[dimHeap + 1];

}
void HeapUp(int x)
{
    while (Heap[x] < Heap[x / 2] && x > 1)
     {
         Swap(x, x/2);
         x /= 2;
     }

}


void BuildHeap()
{
    for(int i = 1; i <= N; i++)
    {
     Heap[i] = INF;
     PozInHeap[i] = i;
     PozInGraf[i] = i;
     Wh[i] = -1;
    }
    Heap[1] = 0;
    PozInHeap[s] = 1;
    PozInHeap[1] = s;
    PozInGraf[1] = s;
    PozInGraf[s] = 1;
    dimHeap = N;

}
int Dijkstra()
{
    BuildHeap();
    int flow = 0;
    Modifica();
    while (dimHeap)
    {
        extractNod = ExtractMin();
        Dist[extractNod] = Heap[PozInHeap[extractNod]];
        /*if (extractNod == d)
         break*/
        for(Nod *it = a[extractNod]; it; it = it -> Next)
         {
            if (C[extractNod][it->V] - F[extractNod][it->V] > 0)
             if (Heap[PozInHeap[it->V]] > Heap[PozInHeap[extractNod]] + it -> CS)
              {

                Heap[PozInHeap[it->V]] = Heap[PozInHeap[extractNod]] + it -> CS;
                HeapUp(PozInHeap[it->V]);
                Wh[it->V] = extractNod;

              }

         }
    }
    int now = d;
    int min = INF;
    if (Dist[d] != INF)
    {
    while (now != s)
     {
         if (min > C[Wh[now]][now] - F[Wh[now]][now])
          min = C[Wh[now]][now] - F[Wh[now]][now];
         now = Wh[now];
     }
    now = d;
    while (now != s)
     {
          F[Wh[now]][now] += min;
          F[now][Wh[now]] -= min;
          now = Wh[now];
     }
    drum = 1;
    Sum += Dist[d];
    return Sum * min;
    }
    else
     {
     drum = 0;
     return 0;
     }


}
void Flux()
{
        drum = 1;
        while(drum)
        {
            drum = 0;
            Res += Dijkstra();
        }
}

int main()
{


        freopen("fmcm.in","r",stdin);
        freopen("fmcm.out","w",stdout);

        scanf("%d %d %d %d", &N, &M, &s, &d);
        while (M)
         {
             scanf("%d %d %d %d",&x, &y, &c, &z);
             countE++;
             C[x][y] = c;
             sir[countE].x = x;
             sir[countE].y = y;
             sir[countE].dist = z;

             insert(a[x],y,c,z);
             insert(a[y],x,0,-z);
             M--;
         }
         BellmanFord();
       // Modifica();
         Flux();
         printf("%lld",Res);
}