Cod sursa(job #1535078)

Utilizator usermeBogdan Cretu userme Data 24 noiembrie 2015 12:06:50
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.55 kb
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;

const int MAXN=350,INF=2000000000;

//FILE* f = stdin;
//FILE* h = stdout;
FILE* f = fopen("fmcm.in","r");
FILE* h = fopen("fmcm.out","w");

int N, M;

vector<int> graf[1 + MAXN];

int S, D;

int capacitate[1 + MAXN][1 + MAXN];
int cost[1 + MAXN][1 + MAXN];
int flux[1 + MAXN][1 + MAXN];

struct Nod {
  int index;
  int cost;
  const bool operator < (const Nod &b) const {
    return this->cost > b.cost;
  }
};

queue<Nod> q;
priority_queue<Nod> pq;
int fost[1 + MAXN];
int distantaJ[1 + MAXN];
int distantaN[1 + MAXN];
int distanta[1 + MAXN];

int fluxtotal,costtotal;

bool dijkstra(){
  memset(fost,0,sizeof(fost));
  memset(distantaN,0,sizeof(distantaN));
  memset(distanta,0x3f,sizeof(distanta));
  pq.push(Nod({S, 0}));
  distanta[S] = 0;
  fost[S]=S;
  while ( pq.size()>0 ){
    int nod = pq.top().index;
    int costcurent = pq.top().cost;
    pq.pop();
    if (distanta[nod] == costcurent) {
      for ( int i = 0; i < (int)graf[nod].size(); ++i ){
        int vecin = graf[nod][i];
        if (capacitate[nod][vecin]-flux[nod][vecin] > 0){
          if (costcurent+cost[nod][vecin]+distantaJ[nod]-distantaJ[vecin] < distanta[vecin]) {
            pq.push(Nod{vecin,costcurent+cost[nod][vecin]+distantaJ[nod]-distantaJ[vecin]});
            fost[vecin]=nod;
            distantaN[vecin] = distantaN[nod]+cost[nod][vecin];
            distanta[vecin] = costcurent+cost[nod][vecin]+distantaJ[nod]-distantaJ[vecin];
          }
        }
      }
    }
  }
  memcpy(distantaJ, distantaN, sizeof(distantaJ));
  return fost[D] > 0;
}

void johnson(){
  memset(distantaJ,0x3f,sizeof(distantaJ));
  distantaJ[S] = 0;
  q.push({S, 0});
  while (!q.empty()) {
    int nod = q.front().index;
    int costNod = q.front().cost;
    q.pop();
    if (costNod == distantaJ[nod]) {
      //printf("%d %d\n", nod, costNod);
      for (int i = 0; i < (int)graf[nod].size(); ++i) {
        int vecin = graf[nod][i];
        if (costNod + cost[nod][vecin] < distantaJ[vecin]) {
          distantaJ[vecin] = costNod + cost[nod][vecin];
          q.push({vecin, distantaJ[vecin]});
        }
      }
    }
  }
}

int main(void) {
  int i;
  fscanf(f,"%d%d%d%d", &N, &M, &S, &D);
  for (i = 0; i < M; ++i) {
    int x, y, fl, co;
    fscanf(f,"%d%d%d%d", &x, &y, &fl, &co);
    graf[x].push_back(y);
    //graf[y].push_back(x);
    capacitate[x][y] = fl;
    capacitate[y][x] = 0;
    cost[x][y]=co;
    cost[y][x]=-co;
  }
  johnson();
  //*
  for (int i = 1; i <= N; ++i) {
    for (int j = 0; j < (int)graf[i].size(); ++j) {
      int vecin = graf[i][j];
      if (capacitate[vecin][i] == 0) {
        graf[vecin].push_back(i);
      }
    }
  }//*/
  /*
  for (int i = 1; i <= N; ++i) {
    for (int j = 0; j < (int)graf[i].size(); ++j) {
      int vecin = graf[i][j];
      printf("%d %d -> %d\n", i, vecin, costNou[i][vecin]);
    }
  }//*/

  while ( dijkstra() ){
    int nod=D;
    int mincapacitate = INF;
    while (nod != fost[nod]){
      if (capacitate[fost[nod]][nod]-flux[fost[nod]][nod] < mincapacitate)
        mincapacitate = capacitate[fost[nod]][nod]-flux[fost[nod]][nod];
      nod = fost[nod];
    }
    nod=D;
    while (nod != fost[nod]){
      flux[fost[nod]][nod] += mincapacitate;
      flux[nod][fost[nod]] -= mincapacitate;
      nod=fost[nod];
    }
  }
  for ( int i=1;i<=N;++i ){
    fluxtotal+=flux[S][i];
  }
  for ( int i=1;i<=N;++i )
    for ( int j=1;j<=N;++j )
      if ( flux[i][j]>0 )
        costtotal+=flux[i][j]*cost[i][j];

  //fprintf(h,"%d\n", fluxtotal);
  fprintf(h,"%d\n", costtotal);
  return 0;
}