Cod sursa(job #712281)

Utilizator GrimpowRadu Andrei Grimpow Data 13 martie 2012 11:36:32
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.89 kb
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <utility>
#include <queue>
#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 H[NMax],Poz[NMax],Dist[NMax],P[NMax] , C[NMax][NMax] , F[NMax][NMax] , Cost[NMax][NMax];
bool inQue[NMax];
vector<int> ad[NMax];

/*bool cmp(int x,int y){
	return Dist[x]<Dist[y];
}

void change(int x,int y){
	swap(H[x],H[y]);
	swap(Poz[H[x]],Poz[H[y]]);
}*/

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<(int)ad[x].size();++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<(int)ad[i].size();++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));*/

	push(S);
	Dist[S]=0;
	while (L>0)
	{
		x=H[1];pop(H[1]);

		for (i=0;i<(int)ad[x].size();++i)
			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;
}

int main()
{
	int x,y,cap,s;
	freopen(IN,"r",stdin);
	scanf("%d%d%d%d",&N,&M,&S,&D);
	while (M--)
	{
		scanf("%d%d%d%d",&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;
	}

	BellmanFord();

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

	return 0;
}