Pagini recente » Cod sursa (job #2777408) | Cod sursa (job #2876199) | Cod sursa (job #2585973) | Cod sursa (job #507379) | Cod sursa (job #2910581)
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
const long long INF = (1LL << 60);
struct Edge {
int from, to;
int cap, cost;
};
class Graph {
private:
int n;
int src, dst;
vector<Edge> edges;
vector<vector<int>> gr;
vector<long long> d;
public:
Graph(int _n, int _src, int _dst) {
n = _n;
src = _src, dst = _dst;
gr.resize(_n + 1);
d.assign(_n + 1, INF);
}
void addEdge(int from, int to, int cap, int cost) {
gr[from].push_back(edges.size());
edges.push_back({from, to, cap, cost});
gr[to].push_back(edges.size());
edges.push_back({to, from, 0, -cost});
}
void bellmanFord() {
queue<int> q;
vector<bool> inQ(n + 1, false);
d.assign(n + 1, INF);
d[src] = 0, inQ[src] = true;
q.push(src);
while (!q.empty()) {
auto node = q.front();
inQ[node] = false;
q.pop();
for (auto idx: gr[node]) {
auto e = edges[idx];
if (e.cap > 0 && d[e.to] > d[node] + e.cost) {
d[e.to] = d[node] + e.cost;
if (!inQ[e.to]) {
inQ[e.to] = true;
q.push(e.to);
}
}
}
}
}
void assignCost() {
for (auto& e: edges) {
e.cost += d[e.from] - d[e.to];
}
}
bool dijkstra(vector<int>& ant) {
vector<long long> dij(n + 1, INF);
priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;
dij[src] = 0;
pq.push({dij[src], src});
ant.assign(n + 1, -1);
while (!pq.empty()) {
auto p = pq.top();
pq.pop();
int node = p.second;
if (node == dst) {
break;
}
for (auto idx: gr[node]) {
auto e = edges[idx];
if (e.cap > 0 && dij[e.to] > dij[node] + e.cost) {
dij[e.to] = dij[node] + e.cost;
ant[e.to] = idx;
pq.push({dij[e.to], e.to});
}
}
}
return (dij[dst] != INF);
}
pair<long long, long long> maxFlowMinCost() {
bellmanFord();
assignCost();
long long maxFlow = 0, minCost = 0;
vector<int> ant;
while (dijkstra(ant)) {
int minFlow = 2e9;
int node = dst;
while (node != src) {
auto e = edges[ant[node]];
minFlow = min(minFlow, e.cap);
node = e.from;
}
maxFlow += minFlow;
node = dst;
while (node != src) {
auto& e = edges[ant[node]];
auto& re = edges[ant[node] ^ 1];
minCost += (long long) minFlow * (e.cost - (d[e.from] - d[e.to]));
e.cap -= minFlow;
re.cap += minFlow;
node = e.from;
}
}
return {maxFlow, minCost};
}
};
int main() {
ifstream cin("fmcm.in");
ofstream cout("fmcm.out");
int n, m, s, t;
cin >> n >> m >> s >> t;
Graph g(n, s, t);
while (m--) {
int from, to, cap, cost;
cin >> from >> to >> cap >> cost;
g.addEdge(from, to, cap, cost);
}
cin.close();
auto ans = g.maxFlowMinCost();
cout << ans.second << "\n";
cout.close();
return 0;
}