Cod sursa(job #998845)

Utilizator ctlin04UAIC.VlasCatalin ctlin04 Data 18 septembrie 2013 14:31:15
Problema Flux maxim de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.23 kb
#include<fstream>
#include<cstring>
using namespace std;
typedef struct celula{
              int nod;
              celula *next;
              }*lista;
typedef struct {int nod,dist; } tip;
tip heap[355];
lista graf[355],v;
int i,j,n,m,cap[355][355],cost[355][355],s,d,dist[355],x,y,coada[10000],aux[355][355],tata[355],sol,hp;
bool viz[355];

void upheap(int nod) { if (nod>1&&heap[nod].dist<heap[nod/2].dist) { tip w=heap[nod]; heap[nod]=heap[nod/2]; heap[nod/2]=w; upheap(nod/2); }}

void downheap(int nod) {
     if (2*nod<=hp&&heap[2*nod].dist<heap[nod].dist&&(heap[2*nod].dist<heap[2*nod+1].dist||2*nod+1>hp)) { tip w=heap[nod]; heap[nod]=heap[nod*2]; heap[nod*2]=w; downheap(2*nod);}
      else if (2*nod<hp&&heap[2*nod+1].dist<heap[nod].dist&&heap[2*nod+1].dist<heap[2*nod].dist) { tip w=heap[nod]; heap[nod]=heap[nod*2+1]; heap[nod*2+1]=w; downheap(2*nod+1);}
}

void sterge(){
     heap[1]=heap[hp]; --hp; downheap(1);
}

void baga(int nod, int dist) {
     ++hp; heap[hp].nod=nod; heap[hp].dist=dist; upheap(hp);
}

bool exista_drum(){
     memset(viz,0,sizeof(viz)); dist[s]=0;
     viz[s]=s; hp=1; heap[hp].nod=s; heap[hp].dist=0;
     while (hp&&viz[d]==0) {
           int nod=heap[1].nod; sterge();
           for (lista p=graf[nod]; p; p=p->next)
            if (viz[p->nod]==0&&cap[nod][p->nod]>0) { dist[p->nod]=dist[nod]+aux[nod][p->nod];
                                tata[p->nod]=nod; viz[p->nod]=1; baga(p->nod,dist[p->nod]);
                                }
            }
     return(viz[d]);
}

int main(void){
    ifstream fin("fmcm.in");
    ofstream fout("fmcm.out");
    fin>>n>>m>>s>>d;
    for (i=1; i<=m; ++i) {
          fin>>x>>y>>cap[x][y]>>cost[x][y]; cost[y][x]=-cost[x][y];
          v=new celula; v->nod=x; v->next=graf[y]; graf[y]=v;
          v=new celula; v->nod=y; v->next=graf[x]; graf[x]=v;
          }
   //aflu distanta minima cu Ford si modific costurile muchiilor astfel incit sa nu am arce de cost negativ
   int st=1,en=1; coada[1]=s; viz[s]=1;
   for (i=1; i<=n; ++i) dist[i]=1000000000; dist[s]=0;
   while (st<=en) {
          int nod=coada[st];
          for (lista p=graf[nod]; p; p=p->next) 
           if (dist[p->nod]>dist[nod]+cost[nod][p->nod]&&cap[nod][p->nod]>0) {
                                                         dist[p->nod]=dist[nod]+cost[nod][p->nod];
                                                         if (viz[p->nod]==0) { ++en; coada[en]=p->nod; }
                                                         }
          viz[nod]=0; ++st;
          }
   for (i=1; i<=n; ++i)
    for (j=1; j<=n; ++j)
     if (cap[i][j]>0) aux[i][j]=cost[i][j]+dist[i]-dist[j];
   //caut drumuri de ameliorare de cost minim cu Dijkstra
   while (exista_drum()){
         int q=d,mmin=1000000000,sum=0;
         while (q!=s) { mmin=min(mmin,cap[tata[q]][q]); sum+=cost[tata[q]][q]; q=tata[q]; }
         sol+=sum*mmin;
         q=d;
         while (q!=s) {
               cap[tata[q]][q]-=mmin;
               cap[q][tata[q]]+=mmin;
               aux[tata[q]][q]=cost[tata[q]][q]+dist[tata[q]]-dist[q];
               aux[q][tata[q]]=cost[q][tata[q]]+dist[q]-dist[tata[q]];
               q=tata[q];
               }
         }
   fout<<sol;
  return(0);
}