Cod sursa(job #2188420)

Utilizator NeredesinI am not real Neredesin Data 27 martie 2018 09:39:09
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.14 kb
#include <iostream>
#include <fstream>
#include <climits>
#include <vector>
#include <bitset>
#include <queue>

using namespace std;

ifstream in("fmcm.in");
ofstream out("fmcm.out");

const int NMAX = 350;

struct Edge {
  int to;
  int rev;
  int flow;
  int cap;
  int cost;
};

struct Node {
  int node;
  int d;

  bool operator> (Node other) const {
    return d > other.d;
  }
};

int n, m, src, dest;
int dist[1 + NMAX];
int distdij[1 + NMAX];
int prio[1 + NMAX];
int prevnode[1 + NMAX];
int prevedge[1 + NMAX];
int pushflow[1 + NMAX];

vector < Edge > g[1 + NMAX];
bitset < 1 + NMAX > vis;

void addedge(int i, int j, int cap, int cost) {
  Edge direct = {j, g[j].size(), 0, cap, cost};
  Edge inverse = {i, g[i].size(), 0, 0, -cost};

  g[i].push_back(direct);
  g[j].push_back(inverse);
}

void bf() {
  queue < int > q;
  fill(dist + 1, dist + n + 1, INT_MAX);

  dist[src] = 0;
  q.push(src);

  while(!q.empty()) {
    int from = q.front();
    vis[from] = 0;
    q.pop();

    for(int i = 0; i < g[from].size(); i++) {
      Edge &e = g[from][i];
      if(e.flow < e.cap) {
        int to = e.to;
        int newdist = dist[from] + e.cost;
        if(newdist < dist[to]) {
          dist[to] = newdist;
          if(vis[to] == 0) {
            q.push(to);
            vis[to] = 1;
          }
        }
      }
    }
  }
}

void dijkstra() {
  priority_queue < Node, vector < Node >, greater < Node > > pq;
  distdij[src] = 0;
  pq.push({src, distdij[src]});
  vis = 0;
  pushflow[src] = INT_MAX;

  while(!pq.empty()) {
    int from = pq.top().node;
    pq.pop();

    if(vis[from] == 0) {
      vis[from] = 1;
      for(int i = 0; i < g[from].size(); i++) {
        Edge &e = g[from][i];
        if(vis[e.to] == 0) {
          int to = e.to;
          if(e.flow < e.cap) {
            int newdistdij = distdij[from] + e.cost + dist[from] - dist[to];
            if(newdistdij < distdij[to]){
              distdij[to] = newdistdij;
              prevnode[to] = from;
              prevedge[to] = i;
              pushflow[to] = min(pushflow[from], e.cap - e.flow);
              pq.push({to, distdij[to]});
            }
          }
        }
      }
    }
  }
}

void mincostflow(int &flow, int &flowcost) {
  bf();

  flow = flowcost = 0;
  while(distdij[dest] < INT_MAX) {
    fill(distdij + 1, distdij + n + 1, INT_MAX);
    dijkstra();
    if(distdij[dest] < INT_MAX) {

      for(int i = 1; i <= n; i++){
        dist[i] += distdij[i];
      }

      int deltaflow = pushflow[dest];
      flow += deltaflow;
      for(int to = dest; to != src; to = prevnode[to]) {
        Edge &e = g[prevnode[to]][prevedge[to]];
        e.flow += deltaflow;
        g[to][e.rev].flow -= deltaflow;
        flowcost += deltaflow * e.cost;
      }
    }
  }
}

int main()
{
  in >> n >> m >> src >> dest;
  for(int i = 1; i <= m; i++) {
    int x, y, cost, cap;
    in >> x >> y >> cap >> cost;
    addedge(x, y, cap, cost);
  }

  int flow, flowcost;
  mincostflow(flow, flowcost);

  out << flowcost << '\n';

  in.close();
  out.close();
  return 0;
}