MINCOST - Luồng với chi phí nhỏ nhất
Tác giả: RR
Ngôn ngữ: C++
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iomanip>
#include <complex>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <deque>
#include <bitset>
#include <cctype>
#include <utility>
#include <cassert>
#define FOR(i,a,b) for(int i=(a),_b=(b); i<=_b; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b); i>=_b; i--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; i++)
#define EACH(it,a) for(__typeof(a.begin()) it = a.begin(); it != a.end(); ++it)
#define DEBUG(x) { cout << #x << " = "; cout << (x) << endl; }
#define PR(a,n) { cout << #a << " = "; FOR(_,1,n) cout << a[_] << ' '; cout << endl; }
#define PR0(a,n) { cout << #a << " = "; REP(_,n) cout << a[_] << ' '; cout << endl; }
#define sqr(x) ((x) * (x))
using namespace std;
#define prev prev_
const long long F_INF = 1000111000111000LL;
const long long C_INF = 1000111000111000LL;
template<class Flow = long long, class Cost = long long>
struct MinCostFlow {
int V, E;
vector<Flow> cap;
vector<Cost> cost;
vector<int> to, prev;
vector<Cost> dist, pot;
vector<int> last, path, used;
priority_queue< pair<Cost, int> > q;
MinCostFlow(int V, int E) : V(V), E(0), cap(E*2,0), cost(E*2,0), to(E*2,0), prev(E*2,0),
dist(V,0), pot(V,0), last(V, -1), path(V,0), used(V,0) {}
int addEdge(int x, int y, Flow f, Cost c) {
cap[E] = f; cost[E] = c; to[E] = y; prev[E] = last[x]; last[x] = E; E++;
cap[E] = 0; cost[E] = -c; to[E] = x; prev[E] = last[y]; last[y] = E; E++;
return E - 2;
}
pair<Flow, Cost> search(int s, int t) {
Flow ansf = 0; Cost ansc = 0;
REP(i,V) used[i] = false;
REP(i,V) dist[i] = C_INF;
dist[s] = 0; path[s] = -1; q.push(make_pair(0, s));
while (!q.empty()) {
int x = q.top().second; q.pop();
if (used[x]) continue; used[x] = true;
for(int e = last[x]; e >= 0; e = prev[e]) if (cap[e] > 0) {
Cost tmp = dist[x] + cost[e] + pot[x] - pot[to[e]];
if (tmp < dist[to[e]] && !used[to[e]]) {
dist[to[e]] = tmp;
path[to[e]] = e;
q.push(make_pair(-dist[to[e]], to[e]));
}
}
}
REP(i,V) pot[i] += dist[i];
if (used[t]) {
ansf = F_INF;
for(int e=path[t]; e >= 0; e=path[to[e^1]]) ansf = min(ansf, cap[e]);
for(int e=path[t]; e >= 0; e=path[to[e^1]]) { ansc += cost[e] * ansf; cap[e] -= ansf; cap[e^1] += ansf; }
}
return make_pair(ansf, ansc);
}
pair<Flow, Cost> minCostFlow(int s, int t) {
Flow ansf = 0; Cost ansc = 0;
while (1) {
pair<Flow, Cost> p = search(s, t);
if (!used[t]) break;
ansf += p.first; ansc += p.second;
}
return make_pair(ansf, ansc);
}
};
const int MN = 111*111*2;
long long f[111][111], c[111][111];
int id_u[MN], id_v[MN], edges[MN];
int main() {
int n, m, k, s, t;
while (cin >> n >> m >> k >> s >> t) {
MinCostFlow<long long, long long> mcf(n+1, m*2+2);
mcf.addEdge(0, s, k, 0);
memset(f, 0, sizeof f);
FOR(i,1,m) {
int u, v;
cin >> u >> v;
cin >> c[u][v] >> f[u][v];
c[v][u] = c[u][v]; f[v][u] = f[u][v];
}
m = 0;
FOR(i,1,n) FOR(j,i+1,n) if (f[i][j]) {
edges[++m] = mcf.addEdge(i, j, f[i][j], c[i][j]); id_u[m] = i; id_v[m] = j;
edges[++m] = mcf.addEdge(j, i, f[i][j], c[i][j]); id_u[m] = j; id_v[m] = i;
}
pair<long long, long long> res = mcf.minCostFlow(0, t);
if (res.first < k) {
cout << -1 << endl;
continue;
}
cout << res.second << endl;
FOR(i,1,m/2) {
int u = id_u[i], v = id_v[i];
int f_xuoi = f[u][v] - mcf.cap[edges[i*2-1]];
int f_nguoc = f[v][u] - mcf.cap[edges[i*2]];
int t = min(f_xuoi, f_nguoc);
f_xuoi -= t;
f_nguoc -= t;
if (f_xuoi > 0) {
cout << id_u[i*2-1] << ' ' << id_v[i*2-1] << ' ' << f_xuoi << endl;
}
if (f_nguoc > 0) {
cout << id_u[i*2] << ' ' << id_v[i*2] << ' ' << f_nguoc << endl;
}
}
cout << "0 0 0" << endl;
}
}