Pagini recente » Cod sursa (job #542017) | Cod sursa (job #2286328) | Cod sursa (job #1118462) | Cod sursa (job #1218604) | Cod sursa (job #360683)
Cod sursa(job #360683)
#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 nodul
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; st=dr=el=1; deq[1]=s; //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 in care il atin gem
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
}
st++,el--; //inaintam in coada
}
}
void solve()
{
int i;
do
{
bf(s); //facem lant de ameliorare
fm+=y[d]; //adaugam noul flux
cm+=x[d]*y[d]; //aduagam costul acestui flux
//modificam fluxurile ramase
if(y[d])
{
i=d; //nodul destinatie
while(i!=s && i!=(-1)*s)
{ //pana nu ajungem la nodul s
if(i>0) c[z[i]][i]+=y[d]; //se adauga cost pe arc
else c[modul(i)][z[modul(i)]]-=y[d];
i=z[modul(i)];
}
}
}
while(y[d]); //cat timp tot obtinem flux
}
void write()
{
printf("%d\n",cm);
}
int main()
{
freopen(infile,"r",stdin);
freopen(outfile,"w",stdout);
read();
solve();
write();
fclose(stdin);
fclose(stdout);
return 0;
}