Pagini recente » Cod sursa (job #2065942) | Cod sursa (job #2269656) | Cod sursa (job #1428647) | Cod sursa (job #286897) | Cod sursa (job #2949529)
#include <bits/stdc++.h>
using namespace std;
struct Edge
{
int to;
int cap;
int cost;
int inv;
};
const int FN = 350 + 7;
const int FMAXDEG = FN;
const int INF = (int) 1e9 + 7;
int fln;
int fls;
int fld;
Edge fladj[FN][FMAXDEG];
int fltop[FN];
int fldist[FN];
bool flvis[FN];
int flparid[FN];
int ini[FN];
int flflow;
long long flflowcost;
queue<int> flq;
priority_queue<pair<int, int>> flqq;
void flinit(int n, int s, int d)
{
fln = n;
fls = s;
fld = d;
flflow = 0;
flflowcost = 0;
assert(1 <= fls && fls <= fln);
assert(1 <= fld && fld <= fln);
for (int i = 1; i <= fln; i++)
{
fltop[i] = 0;
}
}
void fladdedge(int a, int b, int cap, int cost)
{
assert(1 <= a && a <= fln);
assert(1 <= b && b <= fln);
/// be careful here if you make fltop[a]++ inside :)) like this "fladj[a][++fltop[a]]"
fltop[a]++;
fltop[b]++;
fladj[a][fltop[a]] = {b, cap, cost, fltop[b]};
fladj[b][fltop[b]] = {a, 0, -cost, fltop[a]};
}
bool flbellman()
{
for (int i = 1; i <= fln; i++)
{
fldist[i] = INF;
flvis[i] = 0;
}
flq.push(fls);
flvis[fls] = 1;
fldist[fls] = 0;
while (!flq.empty())
{
int a = flq.front();
assert(flvis[a] == 1);
flvis[a] = 0;
flq.pop();
for (int j = 1; j <= fltop[a]; j++)
{
if (fladj[a][j].cap > 0 && fldist[a] + fladj[a][j].cost < fldist[fladj[a][j].to])
{
fldist[fladj[a][j].to] = fldist[a] + fladj[a][j].cost;
flparid[fladj[a][j].to] = fladj[a][j].inv;
assert(fladj[fladj[a][j].to][fladj[a][j].inv].to == a);
if (!flvis[fladj[a][j].to])
{
flvis[fladj[a][j].to] = 1;
flq.push(fladj[a][j].to);
}
}
}
}
if (fldist[fld] == INF)
{
return 0;
}
int mn = INF, v = fld, s = 0;
while (v != fls)
{
int cur = flparid[v];
/// cout << "v = " << v << "\n";
assert(fladj[fladj[v][cur].to][fladj[v][cur].inv].to == v);
mn = min(mn, fladj[fladj[v][cur].to][fladj[v][cur].inv].cap);
v = fladj[v][cur].to;
}
assert(mn > 0);
v = fld;
while (v != fls)
{
int cur = flparid[v];
assert(fladj[fladj[v][cur].to][fladj[v][cur].inv].to == v);
fladj[fladj[v][cur].to][fladj[v][cur].inv].cap -= mn;
fladj[v][cur].cap += mn;
s += fladj[fladj[v][cur].to][fladj[v][cur].inv].cost;
v = fladj[v][cur].to;
}
#ifdef ONPC
/* cout << s << " vs " << fldist[fld] << "\n";
cout << "fls = " << fls << "\n";
cout << "fld = " << fld << "\n";
for (int i = 1; i <= fln; i++)
{
cout << "fldist[" << i << "] = " << fldist[i] << "\n";
}*/
#endif // ONPC
assert(s == fldist[fld]);
flflow += mn;
flflowcost += 1LL * mn * fldist[fld];
return 1;
}
bool flbellman2()
{
for (int i = 1; i <= fln; i++)
{
ini[i] = fldist[i];
fldist[i] = INF;
}
flqq.push({0, fls});
fldist[fls] = 0;
bool tg = 0;
while (!flqq.empty())
{
pair<int, int> pr = flqq.top();
flqq.pop();
pr.first *= -1;
int a = pr.second;
if (fldist[a] != pr.first)
{
continue;
}
if (a == fld)
{
tg = 1;
}
for (int j = 1; j <= fltop[a]; j++)
{
// cout << a << " " << fladj[a][j].to;
// cout << " : " << ini[fladj[a][j].to] << " | " << fladj[a][j].cost + ini[fladj[a][j].to] << " " << ini[a] << "\n";
if (fladj[a][j].cap == 0)
{
continue;
}
assert(fladj[a][j].cost + ini[a] >= ini[fladj[a][j].to]);
if (fladj[a][j].cap > 0 && fldist[a] + fladj[a][j].cost + ini[a] - ini[fladj[a][j].to] < fldist[fladj[a][j].to])
{
fldist[fladj[a][j].to] = fldist[a] + fladj[a][j].cost + ini[a] - ini[fladj[a][j].to];
flparid[fladj[a][j].to] = fladj[a][j].inv;
flqq.push({-fldist[fladj[a][j].to], fladj[a][j].to});
assert(fladj[fladj[a][j].to][fladj[a][j].inv].to == a);
}
}
}
for (int i = 1; i <= fln; i++)
{
fldist[i] += ini[i];
fldist[i] = min(fldist[i], INF);
}
if (tg == 0)
{
return 0;
}
int mn = INF, v = fld, s = 0;
while (v != fls)
{
int cur = flparid[v];
/// cout << "v = " << v << "\n";
assert(fladj[fladj[v][cur].to][fladj[v][cur].inv].to == v);
mn = min(mn, fladj[fladj[v][cur].to][fladj[v][cur].inv].cap);
v = fladj[v][cur].to;
}
assert(mn > 0);
v = fld;
while (v != fls)
{
int cur = flparid[v];
assert(fladj[fladj[v][cur].to][fladj[v][cur].inv].to == v);
fladj[fladj[v][cur].to][fladj[v][cur].inv].cap -= mn;
fladj[v][cur].cap += mn;
s += fladj[fladj[v][cur].to][fladj[v][cur].inv].cost;
v = fladj[v][cur].to;
}
#ifdef ONPC
/* cout << s << " vs " << fldist[fld] << "\n";
cout << "fls = " << fls << "\n";
cout << "fld = " << fld << "\n";
for (int i = 1; i <= fln; i++)
{
cout << "fldist[" << i << "] = " << fldist[i] << "\n";
}*/
#endif // ONPC
assert(s == fldist[fld]);
flflow += mn;
flflowcost += 1LL * mn * fldist[fld];
return 1;
}
void flpumpflow()
{
if (!flbellman())
{
return;
}
while (flbellman2())
{
}
}
signed main()
{
#ifdef ONPC
freopen ("input.txt", "r", stdin);
#endif // ONPC
#ifndef ONPC
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
freopen ("fmcm.in", "r", stdin);
freopen ("fmcm.out", "w", stdout);
#endif // ONPC
int n, m, s, d;
cin >> n >> m >> s >> d;
flinit(n, s, d);
for (int i = 1; i <= m; i++)
{
int a, b, c, d;
cin >> a >> b >> c >> d;
fladdedge(a, b, c, d);
}
flpumpflow();
cout << flflowcost << "\n";
return 0;
}
/**
**/