Cod sursa(job #420264)

Utilizator irene_mFMI Irina Iancu irene_m Data 18 martie 2010 18:19:16
Problema Flux maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.17 kb
#include <cstdio>
#define infile "fmcm.in"
#define outfile "fmcm.out"
#define MaxN 400
#define Inf 0x3f3f3f3f

struct edge{
      int x;
      edge *next;
}     *G[MaxN],*g[MaxN];

int N,M,S,D,fm,cm;
int c[MaxN][MaxN]; // cost
int cp[MaxN][MaxN]; // capacitate
/*int a[MaxN][MaxN];
int b[MaxN][MaxN]; // transp*/
int sat[MaxN][MaxN];
int Q[MaxN],cmin[MaxN],tt[MaxN],cpmax[MaxN],uz[MaxN];
int ok;

void add(int x,int y)
{
      edge *q=new edge;
      q->x=y; q->next=G[x]; G[x]=q;
      q=new edge;
      q->x=x; q->next=g[y]; g[y]=q;
}

void read()
{
      int i,x,y,z,t;
      scanf("%d%d%d%d",&N,&M,&S,&D);
      for(i=1;i<=M;i++)
      {
            scanf("%d%d%d%d",&x,&y,&t,&z);
            add(x,y);
            cp[x][y]=t; c[x][y]=z;
            c[y][x]=-z;
      }
}

void initial()
{
      int i;
      for(i=1;i<=N;i++)
            uz[i]=tt[i]=cpmax[i]=0, cmin[i]=Inf;
}

int minim(int x,int y)
{
      if(x<y)
            return x;
      return y;
}

void gasire_drum_minim()
{
      int i,p=1,nodc,nod;
      edge *q;
      initial();
      tt[S]=0; uz[S]=1;
      Q[p]=S; cmin[S]=0; cpmax[S]=Inf;
      for(i=1;i<=p;i++)
      {
            nodc=Q[i];
            for(q=G[nodc];q;q=q->next)
            {
                  nod=q->x;
                  if(cp[nodc][nod]>sat[nodc][nod] && cmin[nod]>cmin[nodc]+c[nodc][nod])
                  {
                        cmin[nod]=cmin[nodc]+c[nodc][nod];
                        cpmax[nod]=minim(cpmax[nodc],cp[nodc][nod]-sat[nodc][nod]);
                        tt[nod]=nodc;
                        if(!uz[nod])
                              Q[++p]=nod, uz[nod]=1;
                        if(nod==D)
                              ok=1;
                  }
            }

            for(q=g[nodc];q;q=q->next)
            {
                  nod=q->x;
                  if(sat[nod][nodc]>0 && cmin[nod]>cmin[nodc]-c[nod][nodc])
                  {
                        cmin[nod]=cmin[nodc]+c[nodc][nod];
                        cpmax[nod]=minim(cpmax[nodc],cp[nod][nodc]-sat[nod][nodc]);
                        tt[nod]=-nodc;
                        if(!uz[nod])
                              Q[++p]=nod, uz[nod]=1;
                        if(nod==D)
                              ok=1;
                  }
            }
      }
}

void imbun(int nod)
{
      if(tt[nod])
      {
            if(tt[nod]>0)
            {
                  sat[tt[nod]][nod]+=cpmax[D];
                  imbun(tt[nod]);
            }
            else
            {
                  sat[nod][-tt[nod]]-=cpmax[D];
                  imbun(-tt[nod]);
            }
      }
}

void flow()
{
      do{
            ok=0;
            gasire_drum_minim();
            if(uz[D])
            {
                  fm+=cpmax[D];
                  cm+=cmin[D]*cpmax[D];
                  imbun(D);
            }
      }while(ok);
}

void write()
{
      printf("%d\n",cm);
}

int main()
{
      freopen(infile,"r",stdin);
      freopen(outfile,"w",stdout);

      read();
      flow();
      write();

      fclose(stdin);
      fclose(stdout);
      return 0;
}