Cod sursa(job #2011000)

Utilizator EuAlexOtaku Hikikomori EuAlex Data 14 august 2017 22:06:37
Problema Flux maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 2.69 kb
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>
#include <bitset>
using namespace std;

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

int const nmax = 350;

struct Node {
  int node;
  int p;

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

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

vector <Edge> g[1 + nmax];

int n, m, src, dest;
int dist[1 + nmax], distdij[1 + nmax];
bitset<1 + nmax> vis;
int prevnode[1 + nmax], prevedge[1 + nmax], plusflow[1 + nmax];

void bellmanford() {
  queue <int> q;
  fill(dist + 1, dist + n + 1, INT_MAX);
  dist[src] = 0;
  q.push(src);
  while(!q.empty()) {
    int u = q.front();

    for(int k = 0; k < g[u].size(); ++ k) {
      if(0 < g[u][k].cap) {
        int v = g[u][k].to, c = g[u][k].cost;

        if(dist[u] + c < dist[v]) {
          q.push(v);
          dist[v] = dist[u] + c;
        }
      }
    }
    q.pop();
  }
}

void dijkstra() {
  fill(distdij + 1, distdij + n + 1, INT_MAX);
  priority_queue <Node, vector<Node>, greater<Node> > pq;
  vis = 0;

  distdij[src] = 0;
  pq.push({src, 0});
  vis[src] = 1;
  plusflow[src] = INT_MAX;

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

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

    pq.pop();
  }
}

void mincostflow(int &flow, int &flowcost) {
  flow = flowcost = 0;
  bellmanford();
  while(distdij[dest] < INT_MAX) {
    dijkstra();
    if(distdij[dest] < INT_MAX) {
      int deltaflow = plusflow[dest];
      flow += deltaflow;
      for(int to = dest; to!= src; to = prevnode[to]) {
        Edge &e = g[prevnode[to]][prevedge[to]];
        e.flow += deltaflow;
        g[e.to][e.rev].flow -= deltaflow;
        flowcost += deltaflow * e.cost;
      }
    }

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

int main() {

  cin >> n >> m >> src >> dest;

  for(int i = 1; i <= m; ++ i) {
    int x, y, c, z;
    cin >> x >> y >> c >> z;
    g[x].push_back({y, g[y].size(),  z, c, 0});
    g[y].push_back({x, g[x].size() - 1, -z, 0, 0});
  }

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

  cout << flowcost;
  return 0;
}