Cod sursa(job #2009392)

Utilizator alexnekiNechifor Alexandru alexneki Data 9 august 2017 16:06:46
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.86 kb
#include <queue>
#include <vector>
#include <climits>
#include <iostream>
#include <fstream>
#include <bitset>

using namespace std;

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

int const nmax = 350;

struct Edge {
  int to;
  int rev;
  int flow;
  int cap;
  int cost;
};
vector<Edge> g[1 + nmax];

struct Node {
  int node;
  int prio;

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

int n, m, source, dest;
int dist[1 + nmax], prio[1 + nmax];
bitset<1 + nmax> vis;

int curflow[nmax], prevedge[nmax], prevnode[nmax];

void addedge(int from, int to, int cap, int cost) {
  Edge dir = {to, (int) g[to].size(), 0, cap, cost};
  Edge rev = {from, (int) g[from].size(), 0, 0, -cost};
  g[from].push_back(dir);
  g[to].push_back(rev);
}

void bellmanford() {
  fill(dist + 1, dist + n + 1, INT_MAX);
  dist[source] = 0;

  queue<int> q;
  q.push(source);
  while (!q.empty()) {
    int from = q.front();
    vis[from] = 0;
    q.pop();

    for (int i = 0; i < (int) 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) {
            vis[to] = 1;
            q.push(to);
          }
        }
      }
    }
  }
}

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

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

    priority_queue<Node, vector<Node>, greater<Node> > q;
    prio[source] = 0;
    curflow[source] = INT_MAX;
    q.push({source, prio[source]});

    vis = 0;
    while (!q.empty()) {
      int from = q.top().node;
      q.pop();

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

    if (prio[dest] < INT_MAX) {
      for (int i = 1; i <= n; i++)
        dist[i] += prio[i];
      int df = curflow[dest];
      flow += df;
      for (int to = dest; to != source; to = prevnode[to]) {
        Edge &e = g[prevnode[to]][prevedge[to]];
        e.flow += df;
        g[to][e.rev].flow -= df;
        flowcost += df * e.cost;
      }
    }
  }
}

int main() {
  in >> n >> m >> source >> dest;
  for (int i = 1; i <= m; i++) {
    int from, to, cap, cost;
    in >> from >> to >> cap >> cost;
    addedge(from, to, cap, cost);
  }

  int flow, flowcost;
  mincostflow(flow, flowcost);
  out << flowcost << endl;
  return 0;
}