Cod sursa(job #771602)

Utilizator igsifvevc avb igsi Data 26 iulie 2012 16:01:51
Problema Flux maxim de cost minim Scor 20
Compilator c Status done
Runda Arhiva educationala Marime 3.19 kb
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define inf 2000000000
#define maxn 352

struct list { int v, z; struct list *n; } *G[maxn];
int C[maxn][maxn], F[maxn][maxn], W[maxn][maxn];
int w[maxn], T[maxn], TZ[maxn], D[maxn];
int H[maxn], posInH[maxn], Hsize;
int N, source, sink;

void bellmanford();
void removeNegativeWeights();
int dijkstra();
void up(int pos);
int pop();

int main()
{
	int i, a, b, c, z;
	int flow, cost, minCost;
  struct list *p;
  FILE *in = fopen("fmcm.in", "r");
  FILE *out = fopen("fmcm.out", "w");

  fscanf(in, "%d %d %d %d", &N, &i, &source, &sink);
  for(; i; --i)
  {
    fscanf(in, "%d %d %d %d", &a, &b, &c, &z);
    C[a][b] = c; W[a][b] = z; W[b][a] = -z;
    p = malloc(sizeof(struct list));
    p->v = b; p->z = z; p->n = G[a]; G[a] = p;
    p = malloc(sizeof(struct list));
    p->v = a; p->z = -z; p->n = G[b]; G[b] = p;
  }
  
  bellmanford();
  removeNegativeWeights();
  
  minCost = 0; 
  while( dijkstra() )
  {
  	flow = inf, cost = 0;
  	for(i = sink; i != source; i = T[i])
  		if(flow > C[T[i]][i] - F[T[i]][i])
  			flow = C[T[i]][i] - F[T[i]][i];
  	for(i = sink; i != source; i = T[i])
  	{
  		F[T[i]][i] += flow;
  		F[i][T[i]] -= flow;
  		cost += flow * TZ[i];
  	}
  	minCost += cost;
  }
  
  fprintf(out, "%d\n", minCost);
  
	fclose(out);
  fclose(in);
	return 0;
}

int dijkstra()
{
  int i;
  struct list *p;

  for(i = 1; i <= N; ++i)
    T[i] = 0,
    D[i] = inf,
    H[i] = posInH[i] = i;

  Hsize = N;
  D[source] = 0;
  H[1] = source;
  H[source] = 1;
  posInH[source] = 1;
  posInH[1] = source;

  while(Hsize)
  {
    i = pop();
    if(i == inf) break;
    for(p = G[i]; p; p = p->n)
      if(C[i][p->v] > F[i][p->v] && D[p->v] > D[i] + W[i][p->v])
      {
        D[p->v] = D[i] + W[i][p->v];
        T[p->v] = i;
        TZ[p->v] = p->z;
        up( posInH[p->v] );
      }
  }

  return T[sink];
}

int pop()
{
  int v, pos, next, aux;

  v = H[1];
  H[1] = H[ Hsize-- ];
  posInH[ H[1] ] = 1;

  for(pos = next = 1; 1; pos = next)
  {
    if(pos<<1 <= Hsize && D[H[next]] > D[H[pos<<1]])
      next <<= 1;
    if((pos<<1)+1 <= Hsize && D[H[next]] > D[H[(pos<<1)+1]])
      next = (pos<<1)+1;

    if(next == pos) break;

    aux = H[pos]; H[pos] = H[next]; H[next] = aux;
    posInH[ H[pos] ] = pos;
    posInH[ H[next] ] = next;
  }

  return v;
}


void up(int pos)
{
  int aux, next;
  for(next = pos>>1; pos > 1 && D[H[pos]] < D[H[next]]; pos = next, next >>= 1)
  {
    aux = H[pos]; H[pos] = H[next]; H[next] = aux;
    posInH[ H[pos] ] = pos;
    posInH[ H[next] ] = next;
  }
}

void removeNegativeWeights()
{
	int i, j;
	for(i = 1; i <= N; ++i)
		for(j = 1; j <= N; ++j)
			W[i][j] += w[i] - w[j];
}

void bellmanford()
{
	int choose, i, j, ok, v;
	int Q[2][maxn], inQ[maxn];
	struct list *p;
	
	memset(inQ, 0, sizeof(inQ));
	Q[0][0] = 1;
	Q[0][1] = source;
	choose = 0;
	
	for(i = ok = 1; i < N && ok; ++i)
	{
		Q[1-choose][0] = 0;
		for(ok = 0, j = 1; j <= Q[choose][0]; ++j)
		{
			v = Q[choose][j];
			for(p = G[v]; p; p = p->n)
				if(w[p->v] > w[v] + p->z)
				{
					ok = 1;
					w[p->v] = w[v] + p->z;
					T[p->v] = v;
					if(inQ[p->v] != i)
					{
						Q[1-choose][++Q[1-choose][0]] = p->v;
						inQ[p->v] = i;
					}
				}
		}
		choose = 1 - choose;
	}
}