Pagini recente » Cod sursa (job #3000388) | Cod sursa (job #1493520) | Cod sursa (job #2101449) | Cod sursa (job #1003283) | Cod sursa (job #1740489)
#include <bits/stdc++.h>
using namespace std;
///---------------------------------------------------
const int BUFFER_SIZE = (1 << 16);
char buffer[BUFFER_SIZE];
int position = BUFFER_SIZE;
inline char getChar()
{
if ( position == BUFFER_SIZE )
{
position = 0;
fread(buffer, BUFFER_SIZE, 1, stdin);
}
return buffer[position++];
}
inline int getInt()
{
register int a = 0;
char ch;
int sgn = 1;
do
{
ch = getChar();
} while ( !isdigit(ch) && ch != '-' );
if ( ch == '-' )
{
sgn = -1;
ch = getChar();
}
do
{
a = (a << 3) + (a << 1) + ch - '0';
ch = getChar();
} while ( isdigit(ch) );
return a * sgn;
}
///---------------------------------------------------
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;
N = getInt();
M = getInt();
S = getInt();
T = getInt();
for (int i = 0; i < M; ++i)
{
int x, y, cap, cst;
x = getInt();
y = getInt();
cap = getInt();
cst = getInt();
addEdge(x, y, cap, cst);
addEdge(y, x, 0, -cst);
}
printf("%lld\n", minCostMaxFlow(S, T).second);
return 0;
}