Pagini recente » Cod sursa (job #391583) | Cod sursa (job #856494) | Cod sursa (job #445715) | Cod sursa (job #3162354) | Cod sursa (job #1740485)
#include <bits/stdc++.h>
using namespace std;
constexpr int MAX_N = 350 + 1;
constexpr int MAX_M = 12500 + 1;
constexpr int INF = numeric_limits<int>::max();
using Pair = pair<int,int>;
vector<int> G[MAX_N];
int capacity[MAX_N][MAX_N];
int flow[MAX_N][MAX_N];
int cost[MAX_N][MAX_N];
bool inQueue[MAX_N];
int dist[MAX_N];
int father[MAX_N];
int N, M;
void addEdge(int x, int y, int cap, int cst)
{
G[x].push_back(y);
capacity[x][y] += cap;
cost[x][y] += cst;
}
void bellmanFord(int S)
{
for (int i = 1; i <= N; ++i)
{
dist[i] = INF;
inQueue[i] = false;
}
queue<int> Q;
dist[S] = 0;
inQueue[S] = true;
Q.push(S);
while (!Q.empty())
{
int node = Q.front();
Q.pop();
inQueue[node] = false;
for (int son : G[node])
{
if (capacity[node][son] > flow[node][son] && dist[son] > dist[node] + cost[node][son])
{
dist[son] = dist[node] + cost[node][son];
if (!inQueue[son])
{
inQueue[son] = true;
Q.push(son);
}
}
}
}
}
void updateCosts()
{
for (int i = 1; i <= N; ++i)
{
if (dist[i] != INF)
{
for (int son : G[i])
if (dist[son] != INF)
cost[i][son] += dist[i] - dist[son];
}
}
}
bool diskstra(int S, int T)
{
updateCosts();
for (int i = 1; i <= N; ++i)
{
father[i] = 0;
dist[i] = INF;
}
dist[S] = 0;
father[S] = S;
priority_queue<Pair, vector<Pair>, greater<Pair>> maxHeap;
maxHeap.push({dist[S], S});
while (!maxHeap.empty())
{
auto p = maxHeap.top();
maxHeap.pop();
int node = p.second;
int d = p.first;
if (d != dist[node])
continue;
for (int son : G[node])
{
if (capacity[node][son] > flow[node][son] && dist[son] > dist[node] + cost[node][son])
{
dist[son] = dist[node] + cost[node][son];
father[son] = node;
maxHeap.push({dist[son], son});
}
}
}
return dist[T] != INF;
}
pair<int, long long> minCostMaxFlow(int S, int T)
{
int totalFlow = 0;
long long costTotalFlow = 0;
long long totalDist = 0;
bellmanFord(S);
totalDist = dist[T];
while (diskstra(S, T))
{
int fmin = INF;
int node = T;
while (node != S)
{
fmin = min(fmin, capacity[ father[node] ][node] - flow[ father[node] ][node]);
node = father[node];
}
node = T;
while (node != S)
{
flow[ father[node] ][node] += fmin;
flow[node][ father[node] ] -= fmin;
node = father[node];
}
totalFlow += fmin;
totalDist += dist[T];
costTotalFlow += (long long)fmin * totalDist;
}
return {totalFlow, costTotalFlow};
}
int main()
{
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
int S, T;
scanf("%d%d%d%d", &N, &M, &S, &T);
for (int i = 0; i < M; ++i)
{
int x, y, cap, cst;
scanf("%d%d%d%d", &x, &y, &cap, &cst);
addEdge(x, y, cap, cst);
addEdge(y, x, 0, -cst);
}
printf("%lld\n", minCostMaxFlow(S, T).second);
return 0;
}