Cod sursa(job #298357)

Utilizator RobytzzaIonescu Robert Marius Robytzza Data 5 aprilie 2009 23:49:23
Problema Flux maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.06 kb
//dijkstra cu heapuri
#include <fstream>
#define lg_max 355
#define infinit 1<<30
using namespace std;

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

struct nod
{
    int inf,cost;
    nod *next;
} *sir[lg_max];

int heap[lg_max],dist[lg_max],viz[lg_max],C[lg_max][lg_max];
int n,m,nr,tati[lg_max],S,D,rez;

void adauga(int a,int b,int c)
{
    nod *q=new nod;
    q->inf=a;
    q->cost=c;
    q->next=sir[b];
    sir[b]=q;
}

void citire()
{
    fin>>n>>m>>S>>D;
    int a,b,cost,flux;
    for (int i=0;i<m;i++)
    {
        fin>>a>>b>>flux>>cost;
        cost+=1001;
        adauga(b,a,cost);
        adauga(a,b,-cost);
        C[a][b]=flux;
    }
}

void initializare()
{
    for (int i=1;i<=n;i++)
    {
        heap[i]=i;
        dist[i]=infinit;
        viz[i]=-1;
    }
    nr++;
    dist[S]=0;
    heap[1]=S;
    viz[S]=1;
}

void schimba(int a,int b)
{
    int aux=heap[a];
    heap[a]=heap[b];
    heap[b]=aux;
}

void in_jos(int poz)
{
    while (poz<=nr)
    {
         int c=poz;
         if ((poz<<1)>nr)
             return;
         c=poz<<1;
         if ( c+1<=nr)
             if ( dist[heap[c+1]] < dist[heap[c]])
                 c++;
         if (dist[heap[poz]]<= dist[heap[c]])
             return;
         viz[heap[poz]]=c;
         viz[heap[c]]=poz;
         schimba(poz,c);
         poz=c;
    }

}

void in_sus(int poz)
{
    while (poz>1)
    {
        if (dist[heap[poz]]<dist[heap[poz>>1]])
        {
            viz[heap[poz]]=poz>>1;
            viz[heap[poz>>1]]=poz;
            schimba(poz,poz>>1);
            poz=poz>>1;
        }
        else
            return ;
    }
}

void dijkstra()
{
    int min;
    initializare();
    nr=1;
    while (nr)
    {
        min=heap[1];
        schimba(1,nr);
        viz[heap[1]]=1;
        nr--;
        in_jos(1);
        for (nod *i=sir[min];i;i=i->next)
            if (C[min][i->inf]&& dist[i->inf]>dist[min]+i->cost)
            {
                dist[i->inf]=dist[min]+i->cost;
                tati[i->inf]=min;
                if (viz[i->inf]==-1)
                {
                    nr++;
                    heap[nr]=i->inf;
                    viz[heap[nr]]=nr;
                    in_sus(nr);
                }
                else
                    in_sus(viz[i->inf]);
            }
    }
}

int mini(int a,int b)
{
     return a>b?b:a;
}

void bell()
{
     int flux,poz;
     dijkstra();
     while (dist[D]!=infinit)
     {
          flux=infinit;
          poz=D;
          while (poz!=S)
          {
               flux=mini(flux,C[tati[poz]][poz]);
               poz=tati[poz];
          }

          poz=D;
          int num=0;
          while (poz!=S)
          {
               C[tati[poz]][poz]-=flux;
               C[poz][tati[poz]]+=flux;
               poz=tati[poz];
               num++;
          }
          rez+=flux*(dist[D]-num*1001);
          dijkstra();
     }
}

int main ()
{
    citire();
    bell();
    fout<<rez;
    return 0;
}