Cod sursa(job #1655431)

Utilizator hrazvanHarsan Razvan hrazvan Data 17 martie 2016 23:16:15
Problema Flux maxim de cost minim Scor 20
Compilator c Status done
Runda Arhiva educationala Marime 3.78 kb
#include <stdio.h>
#include <string.h>
#define MAXN 350
#define MAXM 12500
#define INF 2000000000
int ut[MAXN], nd[2 * MAXM], nxt[2 * MAXM], cost[2 * MAXM], cpc[2 * MAXM], fol[2 * MAXM], dr;
int dist[MAXN], q[MAXN * MAXN];
int heap[MAXN], hnod[MAXN], pozh[MAXN], prev[MAXN], mch[MAXN], dijdist[MAXN];
int real[MAXN];

inline void add(int x, int y, int c, int ct){
  nd[dr] = y;
  nxt[dr] = ut[x];
  cost[dr] = ct;
  cpc[dr] = c;
  ut[x] = dr;
  dr++;
}

void bell(int n, int s){
  memset(dist, 0x7f, sizeof dist);
  int poz, dr = 1, st = 0;
  q[0] = s;
  dist[s] = 0;
  while(st < dr){
    poz = ut[q[st]];
    while(poz != -1){
      if(dist[q[st]] + cost[poz] < dist[nd[poz]] && !(poz & 1)){
        dist[nd[poz]] = dist[q[st]] + cost[poz];
        q[dr] = nd[poz];
        dr++;
      }
      poz = nxt[poz];
    }
    st++;
  }
}

inline void intersch(int x, int y){
  int aux;
  pozh[hnod[x]] = y;  pozh[hnod[y]] = x;
  aux = heap[x];  heap[x] = heap[y];  heap[y] = aux;
  aux = hnod[x];  hnod[x] = hnod[y];  hnod[y] = aux;
}

inline void urc(int x){
  while(x > 0 && heap[x] < heap[(x - 1) / 2]){
    intersch(x, (x - 1) / 2);
    x = (x - 1) / 2;
  }
}

inline void cobor(int x, int dr){
  int best;
  char g = 1;
  while(g && 2 * x + 1 < dr){
    best = 2 * x + 1;
    if(2 * x + 2 < dr && heap[2 * x + 2] < heap[best])
      best = 2 * x + 2;
    if(heap[x] > heap[best]){
      intersch(x, best);
      x = best;
    }
    else
      g = 0;
  }
}

void dijkstra(int n, int s){
  memset(pozh, -1, sizeof pozh);
  memset(prev, -1, sizeof prev);
  memset(mch, -1, sizeof mch);
  memset(dijdist, -1, sizeof dijdist);
  int dr = 1, ch, cn, poz, ad;
  heap[0] = 0;
  hnod[0] = s;
  pozh[s] = 0;
  dijdist[s] = 0;
  while(dr > 0){
    dijdist[hnod[0]] = heap[0];
    ch = heap[0];
    cn = hnod[0];
    intersch(0, dr - 1);
    pozh[hnod[dr - 1]] = -1;
    dr--;
    cobor(0, dr);
    poz = ut[cn];
    while(poz != -1){
      if(cpc[poz] - fol[poz] > 0 && dijdist[nd[poz]] == -1){
        if(poz & 1)
          ad = dist[nd[poz - 1]] - dist[nd[poz]];
        else
          ad = dist[nd[poz + 1]] - dist[nd[poz]];
        if(pozh[nd[poz]] == -1){
          prev[nd[poz]] = cn;
          mch[nd[poz]] = poz;
          heap[dr] = ch + cost[poz] + ad;
          real[nd[poz]] = real[cn] + cost[poz];
          hnod[dr] = nd[poz];
          pozh[nd[poz]] = dr;
          urc(dr);
          dr++;
        }
        else  if(heap[pozh[nd[poz]]] > ch + cost[poz] + ad){
          prev[nd[poz]] = cn;
          mch[nd[poz]] = poz;
          heap[pozh[nd[poz]]] = ch + cost[poz] + ad;
          real[nd[poz]] = real[cn] + cost[poz];
          urc(pozh[nd[poz]]);
        }
      }
      poz = nxt[poz];
    }
  }
  int i;
  for(i = 0; i < n; i++)
    dist[i] = real[i];
}

int main(){
  FILE *in = fopen("fmcm.in", "r");
  int n, m, s, d, i, x, y, z, t;
  fscanf(in, "%d%d%d%d", &n, &m, &s, &d);
  s--;  d--;
  memset(ut, -1, sizeof ut);
  for(i = 0; i < m; i++){
    fscanf(in, "%d%d%d%d", &x, &y, &z, &t);
    x--;  y--;
    add(x, y, z, t);
    add(y, x, 0, -t);
  }
  fclose(in);
  bell(n, s);
  int augm = 1, rez = 0, sum;
  while(augm > 0){
    dijkstra(n, s);
    augm = 0;
    if(prev[d] != -1){
      augm = INF;
      x = d;
      sum = 0;
      while(x != s){
        if(augm > cpc[mch[x]] - fol[mch[x]])
          augm = cpc[mch[x]] - fol[mch[x]];
        if(mch[x] & 1)
          sum += cost[mch[x]];
        else
          sum += cost[mch[x]];
        x = prev[x];
      }
      x = d;
      while(x != s){
        fol[mch[x]] += augm;
        x = prev[x];
      }
      rez += augm * sum;
    }
  }
  FILE *out = fopen("fmcm.out", "w");
  fprintf(out, "%d", rez);
  fclose(out);
  return 0;
}