Cod sursa(job #529379)

Utilizator PlayLikeNeverB4George Marcus PlayLikeNeverB4 Data 4 februarie 2011 20:40:43
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.6 kb
#include <stdio.h>
#include <assert.h>
#define maxn 356
#define oo 200000000
#define ll long long

struct nod {
	int inf;
	nod *next;};

int i,N,M,st,dest,hp,S;
ll R;
int A[maxn][maxn],C[maxn][maxn],D[maxn],Cost[maxn][maxn],from[maxn];
int H[maxn],poz[maxn];

void citire()
{
	int x,y,c,z;
	scanf("%d %d %d %d",&N,&M,&st,&dest);
	for(i=1;i<=M;i++)
	{
		scanf("%d %d %d %d",&x,&y,&c,&z);
		A[x][++A[x][0]]=y;
		A[y][++A[y][0]]=x;
		C[x][y]=c; Cost[x][y]=z; Cost[y][x]=-z;
	}
}

void BF(int sursa)
{
	int pi,ps,k,Q[maxn*maxn]; pi=ps=1;
	for(i=1;i<=N;i++) D[i]=oo;
	D[sursa]=0; Q[1]=sursa;
	while(ps<=pi)
	{
		k=Q[ps];
		for(i=1;i<=A[k][0];i++)
			if(C[k][A[k][i]]>0 && D[k]+Cost[k][A[k][i]]<D[A[k][i]])
			{
				pi++;
				D[A[k][i]]=D[k]+Cost[k][A[k][i]];
				Q[++pi]=A[k][i];
			}
		ps++;
	}
	S=D[dest];
}

void costuri_poz()
{
	for(i=1;i<=N;i++)
		for(int j=1;j<=A[i][0];j++)
			if(D[i]!=oo && D[A[i][j]]!=oo)
				Cost[i][A[i][j]]=Cost[i][A[i][j]]+D[i]-D[A[i][j]];
}

inline ll min(ll a, ll b)
{
	if(a>b) return b;
	return a;
}
void swap(int &a,int &b)
{
	int aux=a;
	a=b;
	b=aux;
}
void downheap(int k)
{
	int son;
	do
	{
		son=0;
		if(2*k<=hp)
		{
			son=2*k;
			if(son+1<=hp && D[H[son+1]]<D[H[son]])
				son++;
			if(D[H[son]]>D[H[k]]) son=0;
		}
		if(son)
		{
			swap(poz[H[k]],poz[H[son]]);
			swap(H[k],H[son]);
			k=son;
		}
	}
	while(son);
}
void upheap(int k)
{
	while(k>1 && D[H[k]]<D[H[k/2]])
	{
		swap(poz[H[k]],poz[H[k/2]]);
		swap(H[k],H[k/2]);
		k=k/2;
	}
}
void insert(int k)
{
	H[++hp]=k;
	poz[k]=hp;
	upheap(hp);
}
int radacina()
{
	int r=H[1];
	H[1]=H[hp];
	poz[H[1]]=1;
	poz[H[hp]]=hp;
	hp--;
	downheap(1);
	return r;
}

int dijk()
{
	int k;
	costuri_poz();
	for(i=1;i<=N;i++) { D[i]=oo; poz[i]=0; from[i]=0; H[i]=0; }
	hp=0; D[st]=0; insert(st);
	while(hp)
	{
		k=radacina();
		for(i=1;i<=A[k][0];i++)
		{
			if (C[k][A[k][i]]>0) assert(Cost[k][A[k][i]]>=0);
			if(C[k][A[k][i]]>0 && D[k]+Cost[k][A[k][i]]<D[A[k][i]])
			{
				D[A[k][i]]=D[k]+Cost[k][A[k][i]];
				from[A[k][i]]=k;
				if(poz[A[k][i]]==0)
					insert(A[k][i]);
				else upheap(poz[A[k][i]]);
			}
		}
	}
	if(D[dest]!=oo) return 1;
	return 0;
}

int main()
{
	freopen("fmcm.in","r",stdin);
	freopen("fmcm.out","w",stdout);
	citire();
	BF(st);
	while(dijk())
	{
		int k=dest,fmin=oo;
		do
		{
			fmin=min(fmin,C[from[k]][k]);
			k=from[k];
		}
		while(k!=st);
		k=dest;
		do
		{
			C[from[k]][k]-=fmin;
			C[k][from[k]]+=fmin;
			k=from[k];
		}
		while(k!=st);
		S+=D[dest];
		R+=fmin*S;
	}
	printf("%lld",R);
}