Cod sursa(job #712290)

Utilizator GrimpowRadu Andrei Grimpow Data 13 martie 2012 11:45:22
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.3 kb
#include <stdio.h>
#include <fstream>
#include <string.h>
#include <algorithm>
#include <vector>
#include <utility>
#include <queue>
#include <assert.h>
#define INF 0x3f3f3f3f
#define NMax 351
#define cmp(x,y) ( Dist[x]<Dist[y] )
#define change(x,y) {swap(H[x],H[y]);swap(Poz[H[x]],Poz[H[y]]);}

using namespace std;
typedef long long ll;
const char IN[]="fmcm.in",OUT[]="fmcm.out";

int N,M,S,D,L,Sum;
int  Dist[NMax];
short  C[NMax][NMax] , F[NMax][NMax] ,Cost[NMax][NMax],P[NMax],Poz[NMax],H[NMax] , Size[NMax];
bool inQue[NMax];
vector<int> ad[NMax];

void remake(int x)
{
	int l=2*x,r=l+1,min=x;

	if ( l <= L && cmp(H[l],H[min])) min=l;
	if ( r <= L && cmp(H[r],H[min])) min=r;

	if (min!=x)
	{
		change(min,x);
		remake(min);
	}
}

inline void tryup(int x){
	for (int p=Poz[x];p>1 && cmp(H[p],H[p>>1]);p>>=1)
		change(p,p>>1);
}

inline void push(int x)
{
	if (Poz[x]) return;
	Poz[x]=++L;H[Poz[x]]=x;
	tryup(x);
}

inline void pop(int x)
{
	if (!Poz[x]) return;
	for (int p=Poz[x];p>1;p>>=1)
		change(p,p>>1);
	change(1,L);
	Poz[x]=0;H[L--]=0;
	remake(1);
}

void BellmanFord()
{
	int j,i,x;
	memset(Dist,0x3f,sizeof(Dist));
	Dist[S]=0;
	bool stop=true;
	for (j=0;j<N && stop;++j)
		for (x=1,stop=false;x<=N;++x)
			for (i=0;i<Size[x];++i) if ( C[x][ad[x][i]]>F[x][ad[x][i]] && Dist[x]+Cost[x][ad[x][i]] < Dist[ad[x][i]] )
			{
				stop=true;
				Dist[ad[x][i]]=Dist[x]+Cost[x][ad[x][i]];
			}

	Sum=Dist[D];
}

bool Dijkstra()
{
	int i,j,x;

	for (i=1;i<=N;++i) if (Dist[i]!=INF)
		for (j=0;j<Size[i];++j)
			if ( Dist[ad[i][j]]!=INF ) Cost[i][ad[i][j]]+=Dist[i]-Dist[ad[i][j]];
	for (i=1;i<=N;++i)
		Dist[i]=INF,P[i]=0;
	/*memset(Dist,0x3f,sizeof(Dist));
	memset(P,0,sizeof(P));*/
	L=0;
	push(S);
	Dist[S]=0;
	while (L>0 )
	{
		x=H[1];pop(H[1]);
		//if (x==D) break;
		for (i=0;i<Size[x];++i)
		{
			if ( C[x][ad[x][i]] > F[x][ad[x][i]] ) assert( Cost[x][ad[x][i]]>=0 );
			if ( C[x][ad[x][i]] > F[x][ad[x][i]] && Dist[x]+Cost[x][ad[x][i]]<Dist[ad[x][i]])
		{
			Dist[ad[x][i]]=Dist[x]+Cost[x][ad[x][i]];
			P[ad[x][i]]=x;

			if (Poz[ad[x][i]])
			{
				tryup(ad[x][i]);
				remake(Poz[ad[x][i]]);
			}
			else
				push(ad[x][i]);
		}
		}
	}

	return Dist[D]!=INF;
}

ll flux()
{
	ll ret=0;int p;
	while (Dijkstra())
	{
		int fmin=INF;

		for (p=D;p!=S;p=P[p])
			fmin=min(fmin,C[P[p]][p]-F[P[p]][p]);

		if (!fmin) continue;

		for (p=D;p!=S;p=P[p])
		{
			F[P[p]][p]+=fmin;
			F[p][P[p]]-=fmin;
		}

		Sum+=Dist[D];
		ret+=fmin*Sum;
	}
	return ret;
}

inline void read(int &a,int &b,int &c,int &d)
{
	int t[4],i,j;bool minus;
	static char s[256],*r;
	//scanf("%s",s);r=s;
	gets(s);r=s;
	for (i=0;i<4;++i)
	{
		t[i]=0;minus=false;
		while (*r && (*r<'0' || *r>'9') && *r!='-') ++r;
		if (*r=='-') minus=true,++r;
		while ( '0'<=*r && *r<='9' )
			t[i]= t[i]*10 + *r - '0',
			++r;
		if (minus) t[i]=-t[i];
	}
	a=t[0];b=t[1];c=t[2];d=t[3];
}

int main()
{
	int x,y,cap,s;
	freopen(IN,"r",stdin);
	read(N,M,S,D);
	while (M--)
	{
		read(x,y,cap,s);
		ad[x].push_back(y);
		ad[y].push_back(x);
		C[x][y]=cap;
		Cost[x][y]=s;
		Cost[y][x]=-s;
	}
	for (int i=1;i<=N;++i) Size[i]=ad[i].size();
	BellmanFord();

	freopen(OUT,"w",stdout);
	printf("%lld\n",flux());
	fclose(stdout);

	return 0;
}