Pagini recente » Cod sursa (job #792118) | Cod sursa (job #1351687) | Cod sursa (job #626897) | Cod sursa (job #1484037) | Cod sursa (job #1740518)
#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>;
template<typename T>
class MinHeap
{
private:
vector<T> heap;
public:
MinHeap() : heap(){
}
void push(const T &p)
{
heap.emplace_back(p);
push_heap(heap.begin(), heap.end(), greater<T>());
}
T top() const
{
return heap.front();
}
void pop()
{
pop_heap(heap.begin(), heap.end(), greater<T>());
heap.pop_back();
}
bool empty() const
{
return heap.empty();
}
};
constexpr int NIL = -1;
struct Edge
{
int capacity;
int flow;
int cost;
int node;
int urm;
};
Edge G[2 * MAX_M];
int head[MAX_N];
int pointer[MAX_N];
bool inQueue[MAX_N];
int oldDist[MAX_N], newDist[MAX_N], realDist[MAX_N];
int father[MAX_N];
int N, M;
int counter;
void addEdge(int x, int y, int cap, int cst)
{
G[counter] = {cap, 0, cst, y, head[x]};
head[x] = counter++;
}
void bellmanFord(int S)
{
for (int i = 1; i <= N; ++i)
{
oldDist[i] = INF;
inQueue[i] = false;
}
queue<int> Q;
oldDist[S] = 0;
inQueue[S] = true;
Q.push(S);
while (!Q.empty())
{
int node = Q.front();
Q.pop();
inQueue[node] = false;
for (int p = head[node]; p != NIL; p = G[p].urm)
{
int capacity = G[p].capacity;
int flow = G[p].flow;
int son = G[p].node;
int cost = G[p].cost;
if (capacity > flow && oldDist[son] > oldDist[node] + cost)
{
oldDist[son] = oldDist[node] + cost;
if (!inQueue[son])
{
inQueue[son] = true;
Q.push(son);
}
}
}
}
}
bool diskstra(int S, int T)
{
for (int i = 1; i <= N; ++i)
{
father[i] = 0;
newDist[i] = INF;
realDist[i] = INF;
pointer[i] = NIL;
}
newDist[S] = 0;
realDist[S] = 0;
father[S] = S;
priority_queue<Pair,vector<Pair>,greater<Pair>> minHeap;
minHeap.push({0, S});
while (!minHeap.empty())
{
auto pp = minHeap.top();
minHeap.pop();
int node = pp.second;
int d = pp.first;
if (d != newDist[node])
continue;
for (int p = head[node]; p != NIL; p = G[p].urm)
{
int capacity = G[p].capacity;
int flow = G[p].flow;
int son = G[p].node;
int cost = G[p].cost;
int new_d = oldDist[node] - oldDist[son] + cost + newDist[node];
if (capacity > flow && newDist[son] > new_d)
{
newDist[son] = new_d;
realDist[son] = realDist[node] + cost;
pointer[son] = p;
father[son] = node;
minHeap.push({newDist[son], son});
}
}
}
memcpy(oldDist, realDist, sizeof(realDist));
return newDist[T] != INF;
}
pair<int, int> minCostMaxFlow(int S, int T)
{
int totalFlow = 0;
int costTotalFlow = 0;
bellmanFord(S);
while (diskstra(S, T))
{
int fmin = INF;
int node = T;
while (node != S)
{
fmin = min(fmin, G[ pointer[node] ].capacity - G[ pointer[node] ].flow);
node = father[node];
}
node = T;
while (node != S)
{
G[ pointer[node] ].flow += fmin;
G[ pointer[node] ^ 1 ].flow -= fmin;
node = father[node];
}
totalFlow += fmin;
costTotalFlow += fmin * realDist[T];
}
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 = 1; i <= N; ++i)
head[i] = NIL;
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;
}