Cod sursa(job #867323)

Utilizator visanrVisan Radu visanr Data 29 ianuarie 2013 15:57:00
Problema Flux maxim de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.63 kb
#include <fstream>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

#define PII pair<int, int>
#define nmax 360
#define inf 0x3f3f3f3f
#define mp make_pair
#define pb push_back


vector<PII> G[nmax];
bool InQueue[nmax];
int N, M, X, Y, C, S, D, Z, Dist[nmax], Sum, Heap[nmax], Pos[nmax], L;
int Capacity[nmax][nmax], CurrentFlow[nmax][nmax], Father[nmax];


void BellmanFord()
{
     int node, i;
     for(i = 1; i <= N; i++) Dist[i] = inf;
     Dist[S] = 0;
     queue<int> Q;
     InQueue[S] = 1;
     Q.push(S);
     while(!Q.empty())
     {
                      node = Q.front();
                      Q.pop();
                      InQueue[node] = false;
                      for(vector<PII> :: iterator it = G[node].begin(); it != G[node].end(); ++it)
                                      if(Dist[it -> first] > Dist[node] + it -> second)
                                                 if(Capacity[node][it -> first] > CurrentFlow[node][it -> first])
                                                 {
                                                      Dist[it -> first] = Dist[node] + it -> second;
                                                      if(!InQueue[it -> first])
                                                      {
                                                                          InQueue[it -> first] = 1;
                                                                          Q.push(it -> first);
                                                      }
                                                 }
     }
}

void Update()
{
     int i, j;
     for(i = 1; i <= N; i++)
          for(vector<PII> :: iterator it = G[i].begin(); it != G[i].end(); ++it)
                          it -> second += Dist[i] - Dist[it -> first];
}

void Swap(int &a, int &b)
{
     a ^= b ^= a ^= b;
}

void Up(int poz)
{
     while(poz > 1 && Dist[Heap[poz >> 1]] > Dist[Heap[poz]])
     {
               swap(Heap[poz >> 1], Heap[poz]);
               swap(Pos[Heap[poz >> 1]], Pos[Heap[poz]]);
               poz >>= 1;
     }
}

void Down(int x)
{
     int y = 0;
     while(x != y)
     {
             y = x;
             if(2 * y <= L && Dist[Heap[2 * y]] < Dist[Heap[x]])
                  x = 2 * y;
             if(2 * y + 1 <= L && Dist[Heap[2 * y + 1]] < Dist[Heap[x]])
                  x = 2 * y + 1;
             swap(Heap[x], Heap[y]);
             swap(Pos[Heap[x]], Pos[Heap[y]]);
     }
}

void Push(int x)
{
     Heap[++ L] = x, Pos[x] = L;
     Up(L);
}

int Pop()
{
    int now = Heap[1];
    swap(Heap[1], Heap[L]);
    swap(Pos[Heap[1]], Pos[Heap[L]]);
    Heap[L] = Pos[Heap[L]] = 0;
    L --;
    Down(1);
    return now;
}

bool Dijkstra()
{
    int i, node;
    for(i = 1; i <= N; i++)
          Dist[i] = inf;
    Dist[S] = 0;
    Push(S);
    while(L)
    {
                     int node = Pop();
                     for(vector<PII> :: iterator it = G[node].begin(); it != G[node].end(); ++it)
                            if(Dist[it -> first] > Dist[node] + it -> second)
                               if(Capacity[node][it -> first] > CurrentFlow[node][it -> first])
                               {
                                      Dist[it -> first] = Dist[node] + it -> second;
                                      Father[it -> first] = node;
                                      if(Pos[it -> first]) Up(Pos[it -> first]);
                                      else Push(it -> first);
                               }
    }
    return Dist[D] != inf;
}


int main()
{
    ifstream in("fmcm.in");
    ofstream out("fmcm.out");
    int i, j;
    in >> N >> M >> S >> D;
    for(i = 1; i <= M; i++)
    {
          in >> X >> Y >> C >> Z;
          G[X].pb(mp(Y, Z));
          G[Y].pb(mp(X, -Z));
          Capacity[X][Y] = C;
    }
    BellmanFord();
    Update();
    Sum = Dist[D];
    int ans = 0;
    while(Dijkstra())
    {
                      int minFlow = inf, node;
                      for(node = D; node != S; node = Father[node])
                               minFlow = min(minFlow, Capacity[Father[node]][node] - CurrentFlow[Father[node]][node]);
                      for(node = D; node != S; node = Father[node])
                      {
                               CurrentFlow[Father[node]][node] += minFlow;
                               CurrentFlow[node][Father[node]] -= minFlow;
                      }
                      Sum += Dist[D];
                      ans += Sum * minFlow;
                      Update();
    }
    out << ans;