Cod sursa(job #299549)

Utilizator cotofanaCotofana Cristian cotofana Data 6 aprilie 2009 20:54:52
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.73 kb
#include <cstdio>
#include <vector>
#define dim 360
#define inf 1<<30

using namespace std;

int n, m, s, d, c[dim][dim], cost[dim][dim], dist[dim], f[dim][dim], drum, sum;
int h[dim], p[dim], from[dim], l;
vector<int> g[dim];

void swap(int a, int b)
{
	int t=h[a];
	h[a]=h[b];
	h[b]=t;
}

void sift(int x)
{
	int son, rson, lson;
	do
	{
		son=0;
		lson=x<<1;
		rson=lson+1;
		if (lson<=l) son=lson;
		if (rson<=l && dist[h[rson]]<dist[h[lson]]) son=rson;
		
		if (dist[h[son]]<dist[h[x]] && son)
		{
			swap(x, son);
			p[h[x]]=x;
			p[h[son]]=son;
			x=son;
		}
		else son=0;
	} while (son);
}

void percolate(int x)
{
	int father=x>>1;
	while (dist[h[x]]<dist[h[father]] && father)
	{
		swap(x, father);
		p[h[father]]=father;
		p[h[x]]=x;
		x=father;
		father=x>>1;
	}
}

int bellmanford()
{
	int i, stop=0, j;
	for (i=1; i<=n; i++) dist[i]=inf;
	dist[s]=0;
	for (i=1; i<=n && !stop; i++)
	{
		stop=1;
		for (j=1; j<=n; j++)
			for (vector<int>::iterator it=g[j].begin(); it!=g[j].end(); it++)
				if (c[j][*it]-f[j][*it]>0 && dist[j]+cost[j][*it]<dist[*it])
				{
					stop=0;
					dist[*it]=dist[j]+cost[j][*it];
				}
	}
	sum=dist[d];
	return stop;
}

int dijkstra()
{
	int i, minim;
	for (i=1; i<=n; i++)
		for (vector<int>::iterator it=g[i].begin(); it!=g[i].end(); it++)
			if (dist[i]!=inf && dist[*it]!=inf)
				cost[i][*it]+=dist[i]-dist[*it];
	
	for (i=1; i<=n; i++)
	{
		h[i]=i;
		p[i]=i;
		dist[i]=inf;
		from[i]=-1;
	}
	
	dist[s]=0;
	h[1]=s; h[s]=1;
	p[1]=s; p[s]=1;
	l=n;
	
	while (l>1 && dist[h[1]]!=inf)
	{
		minim=h[1];
		
		for (vector<int>::iterator it=g[minim].begin(); it!=g[minim].end(); it++)
			if (c[minim][*it]-f[minim][*it] && dist[minim]+cost[minim][*it]<dist[*it])
			{
				dist[*it]=dist[minim]+cost[minim][*it];
				from[*it]=minim;
				percolate(p[*it]);
			}
			
		h[1]=h[l--];
		p[h[1]]=1;
		if (l>1) sift(1);
	}
	
	if (dist[d]!=inf)
	{
		int vmin=inf;
		drum=1;
		
		for (i=d; i!=s; i=from[i])
			if (c[from[i]][i]-f[from[i]][i]<vmin)
				vmin=c[from[i]][i]-f[from[i]][i];
		
		for (i=d; i!=s; i=from[i])
		{
			f[from[i]][i]+=vmin;
			f[i][from[i]]-=vmin;
		}
		
		sum+=dist[d];
		return vmin*sum;
	}
	return 0;
}

long long flux()
{
	long long rez=0;
	drum=1;
	while (drum)
	{
		drum=0;
		rez+=dijkstra();
	}
	return rez;
}

int main()
{
	int i, x, y, cap, cos;
	freopen("fmcm.in", "r", stdin);
	freopen("fmcm.out", "w", stdout);
	scanf("%d %d %d %d\n", &n, &m, &s, &d);
	for (i=1; i<=m; i++)
	{
		scanf("%d %d %d %d\n", &x, &y, &cap, &cos);
		g[x].push_back(y);
		g[y].push_back(x);
		c[x][y]=cap;
		cost[x][y]=cos;
		cost[y][x]=-cos;
	}
	bellmanford();
	printf("%lld\n", flux());
	return 0;
}