Pagini recente » Cod sursa (job #2861076) | Cod sursa (job #683894) | Cod sursa (job #2077149) | Cod sursa (job #2167414) | Cod sursa (job #360871)
Cod sursa(job #360871)
#include<stdio.h>
#define infile "fmcm.in"
#define outfile "fmcm.out"
#define nmax 351
#define mmax 12501
#define inf ~(1<<31)
int ca[nmax][nmax]; //capacitatea arcului
int co[nmax][nmax]; //costul arcului
int a[nmax][nmax]; //graful normal
int b[nmax][nmax]; //graful transpus
int c[nmax][nmax]; //cat a fost saturat din arc
char viz[nmax]; //vector de vizite, pentru a sti daca un nod se afla in coada sau nu (la Bellman Ford)
int x[nmax]; //in BF, costul minim cu care se poate atinge fiecare nod
int y[nmax]; //in BF, capacitatea maxima cu care se poate atinge fiecare nod
int z[nmax]; //in BF, nodul din car atingem nodul curent (va fi negativ, daca arcul va fi parcurs in sens invers)
int n,m; //numarul de noduri, respectiv muchii
int s,d; //nodul sursa si nodul destinatie
int fm,cm; //fluxul maxim si costul minim
inline int modul(int a)
{
if(a<0) return (-1)*a; return a;
}
inline int min(int a, int b)
{
if(a<b) return a; return b;
}
void read()
{
int i,x,y,u,z;
scanf("%d %d %d %d\n",&n,&m,&s,&d);
for(i=1;i<=m;i++)
{ //citim arcele
scanf("%d %d %d %d\n",&x,&y,&u,&z);
a[x][++a[x][0]]=y; //adaugam arcul in graful normal
b[y][++b[y][0]]=x; //adaugam arcul in graful transpus
ca[x][y]=u; //capacitatea arcului
co[x][y]=z; //costul arcului
}
}
//Bellman Ford
void bf(int s)
{
int i;
int deq[nmax]; //coada
int st,dr,el; //capetele cozii, si numarul de elemente din coada
for(i=0;i<=n;i++)
{
x[i]=inf;
viz[i]=y[i]=z[i]=0;
}
x[s]=0; y[s]=inf; viz[s]=1; deq[1]=s; st=dr=el=1; //punem nodul sursa in coada
while(el)
{ //cag timp avem noduri in coada
s=deq[st%nmax]; //nodul curent
for(i=1;i<=a[s][0];i++) //parcurgem toti vecinii din graful normal
if(x[s]+co[s][a[s][i]] < x[a[s][i]] && ca[s][a[s][i]]-c[s][a[s][i]]>0) //daca ajung cu un cost mai mic la nod, si daca putem ajunge
{
x[a[s][i]]=x[s]+co[s][a[s][i]]; //salvam noul cost
y[a[s][i]]=min(y[s],ca[s][a[s][i]]-c[s][a[s][i]]); //salvam capacitatea maxima cu care il putem atinge
z[a[s][i]]=s; //nodul din care il atingem
if(!viz[a[s][i]]) //daca nodul nu este daja in coada
{ viz[a[s][i]]=1; dr++; el++; deq[dr%nmax]=a[s][i]; } //il punem in coada
}
for(i=1;i<=b[s][0];i++) //parcurgem toti vecinii din graful transpus
if(c[b[s][i]][s] && x[s]-co[b[s][i]][s] < x[b[s][i]]) //daca am flux pe arc, si daca ajung cu un cost mai mic
{
x[b[s][i]]=x[s]-co[b[s][i]][s]; //salvam noul cost
y[b[s][i]]=min(y[s],c[b[s][i]][s]); //salvam capacitatea maxima cu care ajungem
z[b[s][i]]=(-1)*s; //nodul din care il atingem
if(!viz[b[s][i]]) //daca nodul nu se afla deja in coada
{ viz[b[s][i]]=1; dr++; el++; deq[dr%nmax]=b[s][i]; }//il punem in coada
}
viz[s]=0; st++,el--; //inaintam in coada
}
}
void solve()
{
int i;
do
{
bf(s); //facem lant de ameliorare
//printf("%d %d\n",x[d],y[d]);
fm+=y[d]; //adaugam noul flux
cm+=x[d]*y[d]; //aduagam costul acestui flux
//modificam fluxurile ramase
if(x[d]!=inf)
{
i=d; //nodul destinatie
while(i!=s)
{ //pana nu ajungem la nodul s
if(z[i]>0) c[z[i]][i]+=y[d]; //se adauga cost pe arc
else c[i][z[modul(i)]]-=y[d];
i=modul(z[i]);
}
}
}
while(x[d]!=inf); //cat timp tot obtinem flux
}
void write()
{
//printf("%d %d\n",fm,cm);
printf("%d\n",cm);
}
int main()
{
freopen(infile,"r",stdin);
freopen(outfile,"w",stdout);
read();
solve();
write();
fclose(stdin);
fclose(stdout);
return 0;
}