Cod sursa(job #339815)

Utilizator razvi9Jurca Razvan razvi9 Data 11 august 2009 17:46:11
Problema Flux maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 1.84 kb
#include<cstdio>
#include<vector>

#define MIN(a,b) (a)<(b)?(a):(b)
#define MAX 351
#define ADD 20000
#define INF 0x7fffffff

int n,m,S,D,i,j,C[MAX][MAX],cost[MAX][MAX],F[MAX][MAX],t[MAX],flow,min,Cost;
std::vector<int> a[MAX];

int d[MAX],h[MAX],poz[MAX];

inline void swap(int x,int y)
{
	int aux = h[x];
	h[x] = h[y];
	h[y] = aux;
	poz[h[x]] = x;
	poz[h[y]] = y;
}

void heapUp(int p)
{
	if(p<=1) return;
	int t = p>>1;
	if(d[h[t]]>d[h[p]])
	{
		swap(t,p);
		heapUp(t);
	}
}

void heapDown(int x)
{
	int l,r,p;
	l = x<<1;
	r = l + 1;
	if(l<=m)
	{
		p = l;
		if(r<=m && d[h[r]]<d[h[l]])
			p = r;
		if(d[h[x]]>d[h[p]])
		{
			swap(x,p);
			heapDown(p);
		}
	}
}

int root()
{
	swap(1,m);
	--m;
	heapDown(1);
	return h[m+1];
}

int dijkstra()
{
	memset(t,0,sizeof(t));
	for(i=1;i<=n;++i)
	{
		d[i] = INF;
		h[i] = i;
		poz[i] = i;
	}
	d[S] = 0;
	heapUp(S);
	m = n;

	int i,x;

	while(m)
	{
		x = root();
		if(d[x] == INF || x==D) break;
		for(i=0;i<a[x].size();++i)
			if(C[x][a[x][i]] != F[x][a[x][i]] && d[x] + cost[x][a[x][i]] < d[a[x][i]])
			{
				d[a[x][i]] = d[x] + cost[x][a[x][i]];
				t[a[x][i]] = x;
				heapUp(poz[a[x][i]]);
			}
	}
	return t[D];
}

int main()
{
	freopen("fmcm.in","r",stdin);
	freopen("fmcm.out","w",stdout);
	scanf("%d %d %d %d",&n,&m,&S,&D);
	for(int x,y,z,c;m;--m)
	{
		scanf("%d %d %d %d",&x,&y,&z,&c);
		a[x].push_back(y);
		a[y].push_back(x);
		C[x][y] = z;
		cost[x][y] = c + ADD;
		cost[y][x] = -c + ADD;
	}
	for(;dijkstra();)
	{
		j = D;
		min = INF;
		while(j!=S)
		{
			min = MIN(min,C[t[j]][j]-F[t[j]][j]);
			j = t[j];
		}
		j = D;
		while(j!=S)
		{
			F[t[j]][j] += min;
			F[j][t[j]] -= min;
			Cost += (cost[t[j]][j] - ADD) * min;
			j = t[j];
		}
		flow += min;
	}
	printf("%d",Cost);
	fclose(stdout);
	return 0;
}