Cod sursa(job #2009395)

Utilizator alexnekiNechifor Alexandru alexneki Data 9 august 2017 16:17:18
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.84 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 dijkstra() {
  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);
          }
        }
      }
    }
  }
}

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

  flow = flowcost = 0;
  while (prio[dest] < INT_MAX) {
    fill(prio + 1, prio + n + 1, INT_MAX);
    dijkstra();
    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;
}