Cod sursa(job #333447)

Utilizator mlazariLazari Mihai mlazari Data 22 iulie 2009 20:08:21
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.79 kb
#include<stdio.h>

#define NMAX 353
#define INF 2000000003
#define minim(a,b) (a)<(b)?(a):(b);

struct lista {
  int x;
  lista *next;
};

struct heap {
  int l;
  int w[NMAX],p[NMAX];
};

lista* v[NMAX];
heap h;
long long rez=0;
int n,m,s,d,drum=1,sum;
int dist[NMAX],t[NMAX];
int cap[NMAX][NMAX],cost[NMAX][NMAX],flux[NMAX][NMAX];

void add(lista* &l,int x) {
  lista *q=new lista;
  q->x=x;
  q->next=l;
  l=q;
}

void swap(int &a,int &b) {
  int c=a;
  a=b;
  b=c;
}

void upheap(int x) {
  while((x>1)&&(dist[h.w[x]]<dist[h.w[x>>1]])) {
    swap(h.w[x],h.w[x>>1]);
    swap(h.p[h.w[x]],h.p[h.w[x>>1]]);
    x=x>>1;
  }
}

void downheap(int x) {
  int f;
  while(2*x<=h.l) {
    f=x;
    if(dist[h.w[2*x]]<dist[h.w[f]]) f=2*x;
    if((2*x<h.l)&&(dist[h.w[2*x+1]]<dist[h.w[f]])) f=2*x+1;
    if(f==x) x=h.l;
    else {
      swap(h.w[x],h.w[f]);
      swap(h.p[h.w[x]],h.p[h.w[f]]);
      x=f;
    }
  }
}

int minheap() {
  int min=h.w[1];
  h.w[1]=h.w[h.l];
  h.l--;
  downheap(1);
  return min;
}

void addheap(int x) {
  h.w[++h.l]=x;
  h.p[x]=h.l;
  upheap(h.l);
}

void citeste() {
  int x,y,c,z;
  freopen("fmcm.in","r",stdin);
  scanf("%d %d %d %d",&n,&m,&s,&d);
  for(int i=0;i<m;i++) {
    scanf("%d %d %d %d",&x,&y,&c,&z);
    add(v[x],y);
    add(v[y],x);
    cap[x][y]=c;
    cost[x][y]=z;
    cap[y][x]=0;
    cost[y][x]=-z;
  }
}

void BellmanFord() {
  int i,j;
  lista *q;
  for(i=1;i<=n;i++) dist[i]=INF;
  dist[s]=0;
  for(i=1;i<=n-1;i++) {
    for(j=1;j<=n;j++)
     for(q=v[j];q;q=q->next) {
       if((cap[j][q->x]>0)&&(dist[j]+cost[j][q->x]<dist[q->x])) dist[q->x]=dist[j]+cost[j][q->x];
     }
  }
  sum=dist[d];
}

int Dijkstra() {
  lista *q;
  int i,min;
  for(i=1;i<=n;i++)
   for(q=v[i];q;q=q->next)
    if((dist[i]!=INF)&&(dist[q->x]!=INF)) cost[i][q->x]+=dist[i]-dist[q->x];
  for(i=1;i<=n;i++) {
    dist[i]=INF;
    h.w[i]=i;
    h.p[i]=i;
    t[i]=-1;
  }
  dist[s]=0;
  h.w[1]=s; h.w[s]=1;
  h.p[1]=s; h.p[s]=1;
  h.l=n;
  while((h.l>=1)&&(dist[h.w[1]]!=INF)) {
    min=minheap();
    for(q=v[min];q;q=q->next)
     if((cap[min][q->x]>flux[min][q->x])&&(dist[min]+cost[min][q->x]<dist[q->x])) {
       dist[q->x]=dist[min]+cost[min][q->x];
       t[q->x]=min;
       upheap(h.p[q->x]);
     }
  }
  if(dist[d]!=INF) {
    int vmin=INF;
    drum=1;
    for(i=d;i!=s;i=t[i])
     vmin=minim(vmin,cap[t[i]][i]-flux[t[i]][i]);
    for(i=d;i!=s;i=t[i]) {
      flux[t[i]][i]+=vmin;
      flux[i][t[i]]-=vmin;
    }
    sum+=dist[d];
    return vmin*sum;
  }
  return 0;
}

void scrie() {
  freopen("fmcm.out","w",stdout);
  printf("%lld",rez);
}

int main() {
  citeste();
  BellmanFord();
  while(drum) {
    drum=0;
    rez+=Dijkstra();
  }
  scrie();
  return 0;
}