Cod sursa(job #360667)

Utilizator stocarulCosmin-Mihai Tutunaru stocarul Data 1 noiembrie 2009 14:37:54
Problema Flux maxim de cost minim Scor 20
Compilator c Status done
Runda Arhiva educationala Marime 3.28 kb
#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[s][b[s][i]] && 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[s][b[s][i]]); //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;
}