Problem:
Minimum Cost Flow
Find the minimum cost to send a certain amount of flow through a flow network.
The flow network is a directed graph where each edge $e$ has capacity $c(e)$ and cost $d(e)$. Each edge $e$ can send an amount of flow $f(e)$ where $f(e) \leq c(e)$. Find the minimum value of $\sum_{e} (f(e) \times d(e))$ to send an amount of flow $F$ from source $s$ to sink $t$.
Input
A flow network $G(V,E)$ is given in the following format.
$|V|\;|E|\;F$
$u_0\;v_0\;c_0\;d_0$
$u_1\;v_1\;c_1\;d_1$
:
$u_{|E|1}\;v_{|E|-1}\;c_{|E|-1}\;d_{|E|-1}$
$|V|$, $|E|$, $F$ are the number of vertices, the number of edges, and the amount of flow of the flow network respectively. The vertices in $G$ are named with the numbers $0, 1,..., |V|−1$. The source is $0$ and the sink is $|V|−1$.
$u_i$, $v_i$, $c_i$, $d_i$ represent $i$-th edge of the flow network. A pair of $u_i$ and $v_i$ denotes that there is an edge from $u_i$ to $v_i$, and $c_i$ and $d_i$ are the capacity and the cost of $i$-th edge respectively.
Output
Print the minimum value in a line. If it is impossible to send the flow from the source $s$ to the sink $t$, print
-1
.
Constraints
2 ≤ $|V|$ ≤ 100
1 ≤ $|E|$ ≤ 1000
0 ≤ $F$ ≤ 1000
0 ≤ $c_i$, $d_i$ ≤ 1000
$u_i$ $\ne$ $v_i$
If there is an edge from vertex $x$ to vertex $y$, there is no edge from vertex $y$ to vertex $x$.
Sample Input
4 5 2
0 1 2 1
0 2 1 2
1 2 1 1
1 3 1 3
2 3 2 1
Sample Output
6

Submitted solutions:

code_snippet: #line 1 "playspace/main.cpp"
#include <bits/stdc++.h>
#line 2 "library/gandalfr/graph/flow_graph.hpp"

#line 7 "library/gandalfr/graph/base_graph.hpp"

namespace internal {
template <class Weight> struct _base_edge {
    int v[2];
    Weight cost;
    int id;
    _base_edge() {}
    _base_edge(int from, int to, Weight cost, int id)
        : v{from, to}, cost(cost), id(id) {}

    // x から見た反対側の端点を返す
    int opp(int x) {
        if (x == v[0]) {
            return v[1];
        } else if (x == v[1]) {
            return v[0];
        } else {
            std::abort();
        }
    }

    friend std::ostream &operator<<(std::ostream &os,
                                    const _base_edge<Weight> &e) {
        e.print(os);
        return os;
    }

  protected:
    virtual void print(std::ostream &os) const = 0;
};
} // namespace internal

template <class Weight> struct edge : public internal::_base_edge<Weight> {
    using internal::_base_edge<Weight>::_base_edge;

    edge reverse() const {
        return {this->v[1], this->v[0], this->cost, this->id};
    }

  protected:
    void print(std::ostream &os) const override {
        os << this->v[0] << " " << this->v[1] << " " << this->cost;
    }
};

template <> struct edge<int> : public internal::_base_edge<int> {
    static inline const int cost = 1;
    using internal::_base_edge<int>::_base_edge;
    edge(int _from, int _to, int _id) : _base_edge<int>(_from, _to, 1, _id) {}

    edge reverse() const { return {v[1], v[0], 1, id}; }

  protected:
    void print(std::ostream &os) const override {
        os << this->v[0] << " " << this->v[1];
    }
};

template <class Cost, class Flow>
struct flow_edge : public internal::_base_edge<Cost> {
  private:
    Flow res, cap;
    using internal::_base_edge<Cost>::cost;

  public:
    flow_edge() {}
    flow_edge(int from, int to, Flow res, Flow cap, int id)
        : internal::_base_edge<Cost>(from, to, 1, id), res(res), cap(cap) {}
    flow_edge(int from, int to, Flow res, Flow cap, Cost cost, int id)
        : internal::_base_edge<Cost>(from, to, cost, id), res(res), cap(cap) {
    }

    // x から見たコスト
    Cost get_cost(int x) {
        if (x == this->v[0]) {
            return this->cost;
        } else if (x == this->v[1]) {
            return -this->cost;
        } else {
            std::abort();
        }
    }

    flow_edge reverse() const {
        return {this->v[1], this->v[0], cap - res, cap, this->cost, this->id};
    }

    // x から見た残余
    Flow residual(int x) const {
        if (x == this->v[0]) {
            return res;
        } else if (x == this->v[1]) {
            return cap - res;
        } else {
            std::abort();
        }
    }

    // x から見て残余がゼロか？
    Flow is_full(int x) const {
        if (x == this->v[0]) {
            return res == 0;
        } else if (x == this->v[1]) {
            return cap - res == 0;
        } else {
            std::abort();
        }
    }

    // x から流量を d だけ追加
    void add_flow(int x, Flow d) {
        if (x == this->v[0]) {
            res -= d;
        } else if (x == this->v[1]) {
            res += d;
        } else {
            std::abort();
        }
    }

  protected:
    void print(std::ostream &os) const override {
        os << this->v[0] << " " << this->v[1] << " " << cap - res << "/" << cap;
    }
};

namespace internal {

template <typename Edge> class _base_graph {
  protected:
    int N;
    std::vector<std::vector<Edge *>> G;
    std::vector<std::unique_ptr<Edge>> E;

  public:
    _base_graph(){};
    _base_graph(int n) : N(n), G(n){};
    _base_graph(int n, int m) : N(n), G(n) { E.reserve(m); };

    /**
     * @return ノードの数
     */
    int count_nodes() const { return N; }

    /**
     * @return 辺の数
     */
    int count_edges() const { return E.size(); }

    /**
     * @param n ノード番号
     * @return ノード n からの隣接頂点のリストの const 参照
     */
    const std::vector<Edge *> &operator[](int n) const { return G[n]; }

    /**
     * @return グラフ全体の辺のポインタのリストの const 参照
     */
    const std::vector<std::unique_ptr<Edge>> &edges() const { return E; }

    void print() const {
        std::cout << this->N << " " << this->E.size() << std::endl;
        for (auto &e : this->E)
            std::cout << *e << std::endl;
    }
};
} // namespace internal
#line 4 "library/gandalfr/graph/flow_graph.hpp"

template <typename Cost, typename Flow>
class flow_graph : public internal::_base_graph<flow_edge<Cost, Flow>> {
  public:
    using internal::_base_graph<flow_edge<Cost, Flow>>::_base_graph;
    flow_graph(const flow_graph &other) : flow_graph(other.N) {
        for (auto &e : other.E) {
            add_edge(*e);
        }
    }

    /**
     * @brief ノードの数をn個まで増やす
     * @param n サイズ
     * @attention 今のノード数より小さい数を渡したとき、変化なし
     */
    void expand(int n) {
        if (n <= this->N)
            return;
        this->N = n;
        this->G.resize(n);
    }

    /**
     * @attention 辺の id は保持される
     */
    void add_edge(const flow_edge<Cost, Flow> &e) {
        this->E.emplace_back(std::make_unique<flow_edge<Cost, Flow>>(e));
        this->G[e.v[0]].push_back(this->E.back().get());
        this->G[e.v[1]].push_back(this->E.back().get());
    }

    /**
     * @attention 辺の id は、(現在の辺の本数)番目 が振られる
     */
    void add_edge(int from, int to, Flow capacity) {
        int id = (int)this->E.size();
        flow_edge<Cost, Flow> e(from, to, capacity, capacity, id);
        this->E.emplace_back(std::make_unique<flow_edge<Cost, Flow>>(e));
        this->G[from].push_back(this->E.back().get());
        this->G[to].push_back(this->E.back().get());
    }

    /**
     * @attention 辺の id は、(現在の辺の本数)番目 が振られる
     */
    void add_edge(int from, int to, Cost cost, Flow capacity) {
        int id = (int)this->E.size();
        flow_edge<Cost, Flow> e(from, to, capacity, capacity, cost, id);
        this->E.emplace_back(std::make_unique<flow_edge<Cost, Flow>>(e));
        this->G[from].push_back(this->E.back().get());
        this->G[to].push_back(this->E.back().get());
    }

    Flow Ford_Fulkerson(int s, int t) {
        static_assert(std::is_integral<Flow>::value,
                      "Flow must be an integer type");
        Flow flow = 0;
        while (true) {
            std::vector<bool> vis(this->N, false);
            auto dfs = [&](auto self, int cur, Flow f) -> Flow {
                if (cur == t)
                    return f;
                vis[cur] = true;
                for (auto &e : this->G[cur]) {
                    if (vis[e->opp(cur)] || e->is_full(cur))
                        continue;
                    Flow tmp = self(self, e->opp(cur),
                                    std::min<Flow>(e->residual(cur), f));
                    if (tmp > static_cast<Flow>(0)) {
                        e->add_flow(cur, tmp);
                        return tmp;
                    }
                }
                return static_cast<Flow>(0);
            };
            Flow inc = dfs(dfs, s, std::numeric_limits<Flow>::max());
            if (inc == 0)
                break;
            flow += inc;
        }
        return flow;
    }

    Flow Dinic(int s, int t) {
        const int invalid = std::numeric_limits<int>::max();
        Flow flow = 0;
        while (true) {
            std::vector<int> dist(this->N, invalid);
            dist[s] = 0;
            std::queue<int> q;
            q.push(s);
            while (!q.empty()) {
                int cur = q.front();
                q.pop();
                for (auto &e : this->G[cur]) {
                    int to = e->opp(cur);
                    if (dist[to] != invalid || e->is_full(cur))
                        continue;
                    dist[to] = dist[cur] + 1;
                    q.push(to);
                }
            }
            if (dist[t] == invalid)
                break;

            while (true) {
                auto dfs = [&](auto self, int cur, Flow f) -> Flow {
                    if (cur == s)
                        return f;
                    for (auto &e : this->G[cur]) {
                        int to = e->opp(cur);
                        if (dist[to] != dist[cur] - 1 || e->is_full(to))
                            continue;
                        Flow tmp =
                            self(self, to, std::min<Flow>(e->residual(to), f));
                        if (tmp > static_cast<Flow>(0)) {
                            e->add_flow(to, tmp);
                            return tmp;
                        }
                    }
                    return static_cast<Flow>(0);
                };
                Flow inc = dfs(dfs, t, std::numeric_limits<Flow>::max());
                if (inc == 0)
                    break;
                flow += inc;
            }
        }
        return flow;
    }

    Flow primal_dual(int s, int t, Flow F) {
        const Cost invalid = std::numeric_limits<Cost>::max();
        Cost cst = 0;
        while (F) {
            std::vector<int> prev_path(this->N, -1);
            std::vector<Cost> min_cost(this->N, invalid);
            min_cost[s] = 0;
            
            for (int i = 0; i < this->N; ++i) {
                for (int j = 0; j < this->E.size(); ++j) {
                    auto e = &(this->E[j]);
                    int src = (*e)->v[0], dst = (*e)->v[1];
                    for (int k = 0; k < 2; ++k) {
                        if (min_cost[src] != invalid && !(*e)->is_full(src)) {
                            Cost alt = min_cost[src] + (*e)->get_cost(src);
                            if (min_cost[dst] > alt) {
                                min_cost[dst] = alt; 
                                prev_path[dst] = j;
                            }
                        }
                        std::swap(src, dst);
                    }
                }
            }
            if (min_cost[t] == invalid) return -1;

            Flow f = F;
            int cur = t;
            while (cur != s) {
                auto e = &(this->E[prev_path[cur]]);
                int src = (*e)->v[(*e)->v[0] == cur];
                f = std::min(f, (*e)->residual(src));
                cur = src;
            }
            F -= f;

            cur = t;
            while (cur != s) {
                auto e = &(this->E[prev_path[cur]]);
                int src = (*e)->v[(*e)->v[0] == cur];
                (*e)->add_flow(src, f);
                cst += f * (*e)->get_cost(src);
                cur = src;
            }
        }
        return cst;
    }


};
#line 3 "playspace/main.cpp"
using namespace std;
using ll = long long;
const int INF = 1001001001;
const ll INFLL = 1001001001001001001;
const ll MOD  = 1000000007;
const ll _MOD = 998244353;
#define rep(i, j, n) for(ll i = (ll)(j); i < (ll)(n); i++)
#define rrep(i, j, n) for(ll i = (ll)(n-1); i >= (ll)(j); i--)
#define all(a) (a).begin(),(a).end()
#define debug(a) std::cerr << #a << ": " << a << std::endl
#define LF cout << endl
template<typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
template<typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }
void Yes(bool ok){ std::cout << (ok ? "Yes" : "No") << std::endl; }

int main(void){

    int N, M, F;
    cin >> N >> M >> F;
    flow_graph<int, int> G(N);
    rep(i,0,M) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        G.add_edge(a, b, d, c);
    }
    cout << G.primal_dual(0, N-1, F) << endl;

}
accuracy: 1
time_ms: 10
memory_kb: 3452
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

struct edge {
	int to, cap, rev, cost;
};

int mincostflow(int V, int S, int T, int F, vector<vector<edge> >& G) {
	int ans = 0;
	for (int rep = 0; rep < F; rep++) {
		vector<int> dist(V, INF);
		vector<edge> pre(V, edge{-1, -1});
		dist[S] = 0;
		int counter = 0;
		while (counter != V) {
			vector<int> ndist = dist;
			for (int i = 0; i < V; i++) {
				if (dist[i] != INF) {
					for (edge e : G[i]) {
						if (e.cap > 0 && ndist[e.to] > dist[i] + e.cost) {
							ndist[e.to] = dist[i] + e.cost;
							pre[e.to] = G[e.to][e.rev];
						}
					}
				}
			}
			if (dist == ndist) {
				break;
			}
			dist = ndist;
			counter += 1;
		}
		assert(counter != V);
		if (dist[T] == INF) {
			return INF;
		}
		ans += dist[T];
		int pos = T;
		while (pos != S) {
			edge& e = G[pre[pos].to][pre[pos].rev];
			e.cap -= 1;
			G[e.to][e.rev].cap += 1;
			pos = pre[pos].to;
		}
	}
	return ans;
}

int main() {
	int V, E, F;
	cin >> V >> E >> F;
	vector<vector<edge> > G(V);
	auto add_edge = [&](int va, int vb, int cap, int cost) -> void {
		G[va].push_back(edge{vb, cap, int(G[vb].size()), cost});
		G[vb].push_back(edge{va, 0, int(G[va].size()) - 1, -cost});
	};
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}
	int ans = mincostflow(V, 0, V - 1, F, G);
	cout << (ans != INF ? ans : -1) << endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3500
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

struct edge {
	int to, cap, rev, cost;
};

int mincostflow(int V, int S, int T, int F, vector<vector<edge> >& G) {
	int ans = 0;
	for (int rep = 0; rep < F; rep++) {
		vector<int> dist(V, INF);
		vector<edge> pre(V);
		dist[S] = 0;
		int counter = 0;
		while (counter != V) {
			vector<int> ndist = dist;
			for (int i = 0; i < V; i++) {
				for (edge e : G[i]) {
					if (dist[i] != INF && e.cap > 0 && ndist[e.to] > dist[i] + e.cost) {
						ndist[e.to] = dist[i] + e.cost;
						pre[e.to] = G[e.to][e.rev];
					}
				}
			}
			if (dist == ndist) {
				break;
			}
			dist = ndist;
			counter += 1;
		}
		assert(counter != V);
		if (dist[T] == INF) {
			return INF;
		}
		ans += dist[T];
		int pos = T;
		while (pos != S) {
			edge &e = G[pre[pos].to][pre[pos].rev];
			e.cap -= 1;
			G[e.to][e.rev].cap += 1;
			pos = pre[pos].to;
		}
	}
	return ans;
}

int main() {
	int V, E, F;
	cin >> V >> E >> F;
	vector<vector<edge> > G(V);
	auto add_edge = [&](int a, int b, int c, int d) -> void {
		G[a].push_back(edge{b, c, int(G[b].size()), d});
		G[b].push_back(edge{a, 0, int(G[a].size()) - 1, -d});
	};
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}
	int ans = mincostflow(V, 0, V - 1, F, G);
	cout << (ans != INF ? ans : -1) << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3484
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

struct edge_data {
	int a, b, cap, cost; // a -> b
};

struct edge {
	int to, id;
};

int mincostflow(int V, int S, int T, int F, const vector<edge_data>& es) {
	const int E = es.size();
	vector<vector<edge> > G(V);
	vector<int> cap(2 * E, 0);
	for (int i = 0; i < E; i++) {
		edge_data e = es[i];
		G[e.a].push_back(edge{e.b, i});
		G[e.b].push_back(edge{e.a, i + E});
		cap[i] = e.cap;
	}
	int ans = 0;
	for (int rep = 0; rep < F; rep++) {
		vector<int> dist(V, INF);
		vector<int> pre(V, -1);
		dist[S] = 0;
		int counter = 0;
		while (counter != V) {
			vector<int> ndist = dist;
			for (int i = 0; i < V; i++) {
				for (edge e : G[i]) {
					int ncost = (e.id < E ? es[e.id].cost : -es[e.id - E].cost);
					if (cap[e.id] > 0 && dist[i] != INF && ndist[e.to] > dist[i] + ncost) {
						ndist[e.to] = dist[i] + ncost;
						pre[e.to] = e.id;
					}
				}
			}
			if (dist == ndist) {
				break;
			}
			dist = ndist;
			counter += 1;
		}
		assert(counter != V);
		if (dist[T] == INF) {
			return INF;
		}
		ans += dist[T];
		int pos = T;
		while (pos != S) {
			int id = pre[pos];
			cap[id] -= 1;
			cap[(id + E) % (2 * E)] += 1;
			pos ^= es[id % E].a ^ es[id % E].b;
		}
	}
	return ans;
}

int main() {
	int V, E, F;
	cin >> V >> E >> F;
	vector<edge_data> es(E);
	for (int i = 0; i < E; i++) {
		cin >> es[i].a >> es[i].b >> es[i].cap >> es[i].cost;
	}
	int ans = mincostflow(V, 0, V - 1, F, es);
	cout << (ans != INF ? ans : -1) << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3476
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

struct edge {
	int to, cap, rev, cost;
};

int mincostflow(int V, int S, int T, int F, vector<vector<edge> >& G) {
	int ans = 0;
	for (int rep = 0; rep < F; rep++) {
		vector<int> dist(V, INF);
		vector<edge> pre(V);
		dist[S] = 0;
		int counter = 0;
		while (counter != V) {
			vector<int> ndist = dist;
			for (int i = 0; i < V; i++) {
				for (edge e : G[i]) {
					if (dist[i] != INF && e.cap > 0 && ndist[e.to] > dist[i] + e.cost) {
						ndist[e.to] = dist[i] + e.cost;
						pre[e.to] = G[e.to][e.rev];
					}
				}
			}
			if (dist == ndist) {
				break;
			}
			dist = ndist;
			counter += 1;
		}
		assert(counter != V);
		if (dist[T] == INF) {
			return INF;
		}
		ans += dist[T];
		int pos = T;
		while (pos != S) {
			edge& e = G[pre[pos].to][pre[pos].rev];
			e.cap -= 1;
			G[e.to][e.rev].cap += 1;
			pos = pre[pos].to;
		}
	}
	return ans;
}

int main() {
	int V, E, F;
	cin >> V >> E >> F;
	vector<vector<edge> > G(V);
	auto add_edge = [&](int a, int b, int c, int d) -> void {
		G[a].push_back(edge{b, c, int(G[b].size()), d});
		G[b].push_back(edge{a, 0, int(G[a].size()) - 1, -d});
	};
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}
	int ans = mincostflow(V, 0, V - 1, F, G);
	cout << (ans != INF ? ans : -1) << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3440
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

struct edge {
	int to, cap, rev, cost;
};

int mincostflow(int V, int S, int T, int F, vector<vector<edge> >& G) {
	int ans = 0;
	for (int rep = 0; rep < F; rep++) {
		vector<int> dist(V, INF);
		vector<edge> pre(V);
		dist[S] = 0;
		int counter = 0;
		while (true) {
			vector<int> ndist = dist;
			for (int i = 0; i < V; i++) {
				if (dist[i] != INF) {
					for (edge e : G[i]) {
						if (e.cap > 0 && ndist[e.to] > dist[i] + e.cost) {
							ndist[e.to] = dist[i] + e.cost;
							pre[e.to] = G[e.to][e.rev];
						}
					}
				}
			}
			if (dist == ndist) {
				break;
			}
			dist = ndist;
		}
		if (dist[T] == INF) {
			return INF;
		}
		ans += dist[T];
		int pos = T;
		while (pos != S) {
			edge &e = G[pre[pos].to][pre[pos].rev];
			e.cap -= 1;
			G[e.to][e.rev].cap += 1;
			pos = pre[pos].to;
		}
	}
	return ans;
}

int main() {
	int V, E, F;
	cin >> V >> E >> F;
	vector<vector<edge> > G(V);
	auto add_edge = [&](int va, int vb, int cap, int cost) -> void {
		G[va].push_back(edge{vb, cap, int(G[vb].size()), cost});
		G[vb].push_back(edge{va, 0, int(G[va].size()) - 1, -cost});
	};
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}
	int ans = mincostflow(V, 0, V - 1, F, G);
	cout << (ans != INF ? ans : -1) << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3440
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

struct edge {
	int to, cap, rev, cost;
};

int mincostflow(int V, int S, int T, int F, vector<vector<edge> >& G) {
	int ans = 0;
	for (int id = 0; id < F; id++) {
		vector<int> dist(V, INF);
		vector<edge> pre(V);
		dist[S] = 0;
		int counter = 0;
		while (counter != V) {
			vector<int> ndist = dist;
			for (int i = 0; i < V; i++) {
				for (edge e : G[i]) {
					if (e.cap > 0 && dist[i] != INF && ndist[e.to] > dist[i] + e.cost) {
						ndist[e.to] = dist[i] + e.cost;
						pre[e.to] = G[e.to][e.rev];
					}
				}
			}
			if (dist == ndist) {
				break;
			}
			dist = ndist;
			counter += 1;
		}
		if (counter == V) {
			return -2;
		}
		if (dist[T] == INF) {
			return INF; // no flow of size F
		}
		int pos = T;
		while (pos != S) {
			edge &e = G[pre[pos].to][pre[pos].rev];
			e.cap -= 1;
			G[e.to][e.rev].cap += 1;
			pos = pre[pos].to;
		}
		ans += dist[T];
	}
	return ans;
}

int main() {
	int V, E, F;
	cin >> V >> E >> F;
	vector<vector<edge> > G(V);
	auto add_edge = [&](int va, int vb, int cap, int cost) -> void {
		G[va].push_back(edge{vb, cap, int(G[vb].size()), cost});
		G[vb].push_back(edge{va, 0, int(G[va].size()) - 1, -cost});
	};
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}
	int ans = mincostflow(V, 0, V - 1, F, G);
	cout << (ans != INF ? ans : -1) << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3436
final_rank: 3

code_snippet: #include<iostream>
#include<cstdio>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<stack>
#include<iomanip>
#include<queue>
#include<set>
#include<functional>
#include<tuple>
#include<bitset>
#include<cassert>
#include<cstdint>
#include<complex>
#include<random>
using namespace std;
bool printb(bool f) {
	if (f)printf("Yes\n");
	else printf("No\n");
	return f;
}
template<class T>
void prt(T t = "", string sep = "\n") { cout << t << sep; return; }
template<class T>
void printl(vector<T> a, string sep = " ") {
	for (int i = 0; i < a.size(); i++) {
		cout << a[i];
		if (i != a.size() - 1)cout << sep;
	}
	if (sep != "\n")cout << "\n";
	return;
}
bool prt_isfixed = false;
template<class T>
void prt_fix(T t, string sep = "\n") {
	if (!prt_isfixed) {
		cout << fixed << setprecision(15);
		prt_isfixed = true;
	}
	prt(t, sep);
}
#define all(a) a.begin(),a.end()
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
using uint = unsigned int;
using llong = long long;
using ullong = unsigned long long;
using pii = pair<int, int>;
using pll = pair<llong, llong>;
using pli = pair<llong, int>;
using pil = pair<int, llong>;
template<typename T> using vec2 = vector<vector<T>>;
template<typename T> inline bool chmin(T& a, T b) { return (a > b) ? (a = b, true) : false; }
template<typename T> inline bool chmax(T& a, T b) { return (a < b) ? (a = b, true) : false; }
bool bitIn(llong a, int b) { return ((a >> b) & 1); }
int bitCnt(llong a) {
	int re = 0;
	while (a > 0) {
		if (a & 1)re++;
		a >>= 1;
	}
	return re;
}
llong powL(llong n, llong i) {
	llong re = 1;
	while (i >= 1) {
		if (i & 1) re *= n;
		n *= n;
		i >>= 1;
	}
	return re;
}

llong powL_M(llong n, llong i, llong mod) {
	llong re = 1;
	while (i >= 1) {
		if (i & 1) {
			re *= n;
			re %= mod;
		}
		n *= n;
		n %= mod;
		i >>= 1;
	}
	return re;
}

struct point {
	llong x = 0, y = 0;
};
int  dx[4] = { 0,1,0,-1 }, dy[4] = { 1,0,-1,0 };

struct edge {
	int to, co;
};


int main() {
	int n, m, k;
	cin >> n >> m >> k;
	vector<int> re(m, 0);
	vector<tuple<int, int, int, int>> e(m);
	rep(i, m) {
		int u, v, c, d;
		scanf("%d %d %d %d", &u, &v, &c, &d);
		e[i] = { u,v,c,d };
	}
	rep(l, k) {

		vector<int>	prev(n, -1);
		vector<int> dis(n, 1e9);
		dis[0] = 0;
		rep(i, n - 1) {
			rep(j, m) {
				auto [u, v, c, d] = e[j];
				if (re[j] != c) {
					if (chmin(dis[v], dis[u] + d))prev[v] = j;
				}
				if (re[j] != 0) {
					if (chmin(dis[u], dis[v] - d))prev[u] = j + m;
				}
			}
		}

		if (prev[n - 1] == -1) {
			prt(-1); return 0;
		}
		int	nv = n - 1;
		while (nv != 0) {
			if (prev[nv] >= m) {
				//逆辺のとき
				re[prev[nv] - m]--;
				nv = get<1>(e[prev[nv] - m]);
			}
			else {
				re[prev[nv]]++;
				nv = get<0>(e[prev[nv]]);
			}
		}
	}
	int ans = 0;
	rep(i, m) {
		auto [u, v, c, d] = e[i];
		ans += re[i] * d;
	}
	prt(ans);

}
accuracy: 1
time_ms: 100
memory_kb: 3532
final_rank: 19

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

struct edge { int to, cap, cost, rev; };

int V, E, F;
vector<edge> G[MAX_N];
int dist[MAX_N];
int prevv[MAX_N];
int preve[MAX_N];

void add_edge(int f, int t, int cap, int cost) {
	edge e1;
	e1.to = t;
	e1.cap = cap;
	e1.cost = cost;
	e1.rev = G[t].size();
	G[f].push_back(e1);
	edge e2;
	e2.to = f;
	e2.cap = 0;
	e2.cost = -cost;
	e2.rev = G[f].size() - 1;
	G[t].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {
	int res = 0;
	while (f > 0) {
		fill(dist, dist + V, INF);
		dist[s] = 0;
		bool update = true;
		while (update) {
			update = false;
			for (int v = 0; v < V; v++) {
				if (dist[v] == INF) continue;
				for (int i = 0; i < G[v].size(); i++) {
					edge& e = G[v][i];
					if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
						dist[e.to] = dist[v] + e.cost;
						prevv[e.to] = v;
						preve[e.to] = i;
						update = true;
					}
				}
			}
		}

		if (dist[t] == INF) {
			return -1;
		}

		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}

		f -= d;
		res += d * dist[t];

		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}
	}
	return res;
}


int main() {


	cin >> V >> E >> F;
	for (int i = 0; i < E; i++) {
		int from, to, c, d;

		cin >> from >> to >> c >> d;
		add_edge(from, to, c, d);
	}

	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50112
final_rank: 17

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

typedef pair<int, int> P;

int V, E, F;
struct edge { int to, cap, cost, rev; };
vector<edge> G[MAX_N];
int h[MAX_N];
int dist[MAX_N];
int prevv[MAX_N], preve[MAX_N];


void add_edge(int from, int to, int cap, int cost) {
	edge e1 = { to, cap, cost, G[to].size() };
	G[from].push_back(e1);
	edge e2 = { from, 0, -cost, G[from].size() - 1 };
	G[to].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {
	
	int res = 0;
	fill(h, h + V, 0);
	while (f > 0) {
		fill(dist, dist + V, INF);
		priority_queue<P, vector<P>, greater<P> > que;
		dist[s] = 0;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			for (int u = 0; u < G[v].size(); u++) {
				edge& e = G[v][u];
				if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
					dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
					prevv[e.to] = v;
					preve[e.to] = u;
					que.push(P(dist[e.to], e.to));

				}
			}
		}


		if (dist[t] == INF) {
			return -1;
		}

		for (int v = 0; v < V; v++) {
			h[v] += dist[v];
		}

		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}

		f -= d;
		res += d * h[t];

		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}

	}
	return res;
}

int main() {

	cin >> V >> E >> F;
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}

	cout << min_cost_flow(0, V - 1, F) << endl;
	
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50064
final_rank: 8

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

int V, E, F;
struct edge { int to, cap, cost, rev; };
vector<edge> G[MAX_N];
int dist[MAX_N];
int prevv[MAX_N], preve[MAX_N];


void add_edge(int from, int to, int cap, int cost) {
	edge e1 = { to, cap, cost, G[to].size() };
	G[from].push_back(e1);
	edge e2 = { from, 0, -cost, G[from].size() - 1 };
	G[to].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {
	
	int res = 0;
	while (f > 0) {
		fill(dist, dist + V, INF);
		dist[s] = 0;
		bool update = true;
		while (update) {
			update = false;
			for (int v = 0; v < V; v++) {
				if (dist[v] == INF) continue;
				for (int i = 0; i < G[v].size(); i++) {
					edge& e = G[v][i];
					if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
						prevv[e.to] = v;
						preve[e.to] = i;
						dist[e.to] = dist[v] + e.cost;
						update = true;
					}
				}
			}
		}

		if (dist[t] == INF) {
			return -1;
		}

		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}

		f -= d;
		res += d * dist[t];

		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}

	}
	return res;
}

int main() {

	cin >> V >> E >> F;
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}

	cout << min_cost_flow(0, V - 1, F) << endl;
	
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50104
final_rank: 14

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

int V, E, F;
typedef pair<int, int> P;
struct edge { int to, cap, cost, rev; };
vector<edge> G[MAX_N];
bool used[MAX_N];
int dist[MAX_N];
int h[MAX_N];
int prevv[MAX_N], preve[MAX_N];

void add_edge(int from, int to, int cap, int cost) {
	edge e1 = { to, cap, cost, G[to].size() };
	G[from].push_back(e1);
	edge e2 = { from, 0, -cost, G[from].size() - 1 };
	G[to].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {

	int res = 0;
	fill(h, h + V, 0);
	while (f > 0) {
		priority_queue < P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		que.push(make_pair(0, s));
		dist[s] = 0;
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			for (int i = 0; i < G[v].size(); i++) {
				edge& e = G[v][i];
				if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
					dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
					prevv[e.to] = v;
					preve[e.to] = i;
					que.push(make_pair(dist[e.to], e.to));
				}
			}
		}

		if (dist[t] == INF) return -1;

		for (int v = 0; v < V; v++) {
			h[v] += dist[v];
		}

		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}
		f -= d;
		res += d * h[t];

		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}

	}
	return res;
}


int main() {

	cin >> V >> E >> F;
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}

	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50100
final_rank: 13

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

int V, E, F;
typedef pair<int, int> P;
struct edge { int to, cap, cost, rev; };
vector<edge> G[MAX_N];
bool used[MAX_N];
int dist[MAX_N];
int h[MAX_N];
int prevv[MAX_N], preve[MAX_N];

void add_edge(int from, int to, int cap, int cost) {
	edge e1 = { to, cap, cost, G[to].size() };
	G[from].push_back(e1);
	edge e2 = { from, 0, -cost, G[from].size() - 1 };
	G[to].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {

	int res = 0;
	fill(h, h + V, 0);
	while (f > 0) {
		priority_queue < P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		que.push(make_pair(0, s));
		dist[s] = 0;
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			for (int i = 0; i < G[v].size(); i++) {
				edge& e = G[v][i];
				if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
					dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
					prevv[e.to] = v;
					preve[e.to] = i;
					que.push(make_pair(dist[e.to], e.to));
				}
			}
		}

		if (dist[t] == INF) return -1;

		for (int v = 0; v < V; v++) {
			h[v] += dist[v];
		}

		int d = f;
		for (int v = t; v != t; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}
		f -= d;
		res += d * h[t];

		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}

	}
	return res;
}


int main() {

	cin >> V >> E >> F;
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}

	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 0.03125
time_ms: 10
memory_kb: 49996
final_rank: 20

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

int V, E, F;
struct edge { int to, cap, cost, rev; };
vector<edge> G[MAX_N];
bool used[MAX_N];
int dist[MAX_N];
int prevv[MAX_N], preve[MAX_N];

void add_edge(int from, int to, int cap, int cost) {
	edge e1 = { to, cap, cost, G[to].size() };
	G[from].push_back(e1);
	edge e2 = { from, 0, -cost, G[from].size() - 1 };
	G[to].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {

	int res = 0;
	while (f > 0) {
		fill(dist, dist + V, INF);
		dist[s] = 0;
		bool update = true;
		while (update) {
			update = false;
			for (int v = 0; v < V; v++) {
				if (dist[v] == INF) continue;
				for (int i = 0; i < G[v].size(); i++) {
					edge& e = G[v][i];
					if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
						dist[e.to] = dist[v] + e.cost;
						prevv[e.to] = v;
						preve[e.to] = i;
						update = true;
					}
				}
			}
		}

		if (dist[t] == INF) {
			return -1;
		}
		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}
		f -= d;
		res += d * dist[t];

		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}

	}
	return res;
}


int main() {

	cin >> V >> E >> F;
	for (int i = 0; i < E; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		add_edge(a, b, c, d);
	}

	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50092
final_rank: 11

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

typedef pair<int, int> P;

int V, E, F;
struct edge { int to, cap, cost, rev; };
vector<edge> G[MAX_N];
int h[MAX_N];
int dist[MAX_N];
int prevv[MAX_N], preve[MAX_N];

void add_edge(int from, int to, int cap, int cost) {
	edge e1;
	e1.to = to; e1.cap = cap; e1.cost = cost; e1.rev = G[to].size();
	G[from].push_back(e1);
	edge e2;
	e2.to = from; e2.cap = 0; e2.cost = -cost; e2.rev = G[from].size() - 1;
	G[to].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {
	int res = 0;
	fill(h, h + V, 0);
	while (f > 0) {
		priority_queue<P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.push(make_pair(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			for (int i = 0; i < G[v].size(); i++) {
				edge& e = G[v][i];
				if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
					dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
					prevv[e.to] = v;
					preve[e.to] = i;
					que.push(make_pair(dist[e.to], e.to));
				}
			}
		}
		if (dist[t] == INF) {
			return -1;
		}

		for (int v = 0; v < V; v++) {
			h[v] += dist[v];
		}

		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(G[prevv[v]][preve[v]].cap, d);
		}
		f -= d;
		res += d * h[t];
		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}
	}
	return res;

}

int main() {

	cin >> V >> E >> F;

	for (int i = 0; i < E; i++) {
		int u, v, c, d;
		cin >> u >> v >> c >> d;
		add_edge(u, v, c, d);
	}

	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50108
final_rank: 16

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

int V, E, F;
struct edge { int to, cap, cost, rev; };
vector<edge> G[MAX_N];
int dist[MAX_N];
int prevv[MAX_N], preve[MAX_N];

void add_edge(int from, int to, int cap, int cost) {
	edge e1;
	e1.to = to; e1.cap = cap; e1.cost = cost; e1.rev = G[to].size();
	G[from].push_back(e1);
	edge e2;
	e2.to = from; e2.cap = 0; e2.cost = -cost; e2.rev = G[from].size() - 1;
	G[to].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {
	int res = 0;
	while (f > 0) {
		fill(dist, dist + V, INF);
		dist[s] = 0;
		bool update = true;
		while (update) {
			update = false;
			for (int v = 0; v < V; v++) {
				if (dist[v] == INF) continue;
				for (int i = 0; i < G[v].size(); i++) {
					edge &e = G[v][i];
					if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
						dist[e.to] = dist[v] + e.cost;
						prevv[e.to] = v;
						preve[e.to] = i;
						update = true;
					}
				}
			}
		}
		if (dist[t] == INF) {
			return -1;
		}

		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}
		f -= d;
		res += d * dist[t];

		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;

		}
	}
	return res;

}

int main() {

	cin >> V >> E >> F;

	for (int i = 0; i < E; i++) {
		int u, v, c, d;
		cin >> u >> v >> c >> d;
		add_edge(u, v, c, d);
	}



	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50068
final_rank: 9

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

typedef pair<int, int> P;
struct edge { int to, cap, cost, rev; };

int V, E, F;
vector<edge> G[MAX_N];
int h[MAX_N];
int dist[MAX_N];
int prevv[MAX_N], preve[MAX_N];

void add_edge(int from, int to, int cap, int cost) {
	edge e1;
	e1.to = to; e1.cap = cap; e1.cost = cost; e1.rev = G[to].size();
	G[from].push_back(e1);
	edge e2;
	e2.to = from; e2.cap = 0; e2.cost = -cost; e2.rev = G[from].size() - 1;
	G[to].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {
	int res = 0;
	fill(h, h + V, 0);

	while (f > 0) {
		priority_queue<P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			
			for (int i = 0; i < G[v].size(); i++) {
				edge& e = G[v][i];
				if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
					dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
					prevv[e.to] = v;
					preve[e.to] = i;
					que.push(P(dist[e.to], e.to));
				}
			}
		}
		if (dist[t] == INF) {
			return -1;
		}
		for (int v = 0; v < V; v++) h[v] += dist[v];

		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}
		f -= d;

		res += d * h[t];
		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}
	}
	return res;
}



int main() {

	cin >> V >> E >> F;
	for (int i = 0; i < E; i++) {
		int u, v, c, cost;
		cin >> u >> v >> c >> cost;
		add_edge(u, v, c, cost);
	}

	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50112
final_rank: 17

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

struct edge { int to, cap, cost, rev; };

int V, E, F;
vector<edge> G[MAX_N];
int dist[MAX_N];
int prevv[MAX_N], preve[MAX_N];

void add_edge(int from, int to, int cap, int cost) {
	edge e1;
	e1.to = to; e1.cap = cap; e1.cost = cost; e1.rev = G[to].size();
	G[from].push_back(e1);
	edge e2;
	e2.to = from; e2.cap = 0; e2.cost = -cost; e2.rev = G[from].size() - 1;
	G[to].push_back(e2);
}

int min_cost_flow(int s, int t, int f) {
	int res = 0;
	while (f > 0) {
		fill(dist, dist + V, INF);
		dist[s] = 0;
		bool update = true;
		while (update) {
			update = false;
			for (int v = 0; v < V; v++) {
				if (dist[v] == INF) continue;
				for (int i = 0; i < G[v].size(); i++) {
					edge& e = G[v][i];
					if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
						dist[e.to] = dist[v] + e.cost;
						prevv[e.to] = v;
						preve[e.to] = i;
						update = true;
					}
				}
			}
		}
		if (dist[t] == INF) {
			return -1;
		}

		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}
		f -= d;

		res += d * dist[t];
		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}

	}
	return res;
}



int main() {

	cin >> V >> E >> F;
	for (int i = 0; i < E; i++) {
		int u, v, c, cost;
		cin >> u >> v >> c >> cost;
		add_edge(u, v, c, cost);
	}

	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50092
final_rank: 11

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

// Minimum Cost Flow (Dijkstra)
// https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_6_B&lang=ja
// 蟻本 p. 203
// 始点0, 終点V-1

int V, E, F;
struct edge { int to, cap, cost, rev; };
typedef pair<int, int> P;

vector<edge> G[MAX_N];
int h[MAX_N];
int dist[MAX_N];
int prevv[MAX_N], preve[MAX_N];

// from からtoへ向かう容量cap, コストcostの辺をグラフに追加する
void add_edge(int from, int to, int cap, int cost) {
	edge e1 = { to, cap, cost, G[to].size() };
	G[from].push_back(e1);
	edge e2 = { from, 0, -cost, G[from].size() - 1 };
	G[to].push_back(e2);
}

// sからtへの流量f最小費用流を求める
// 流せない場合は-1を返す
int min_cost_flow(int s, int t, int f) {
	int res = 0;
	fill(h, h + V, 0);
	while (f > 0) {
		// ダイクストラ法を用いてhを更新する
		priority_queue<P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) {
				continue;
			}
			for (int i = 0; i < G[v].size(); i++) {
				edge& e = G[v][i];
				if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
					dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
					prevv[e.to] = v;
					preve[e.to] = i;
					que.push(P(dist[e.to], e.to));
				}
			}
		}
		if (dist[t] == INF) {
			return -1;
		}
		for (int v = 0; v < V; v++) {
			h[v] += dist[v];
		}

		// s-t間最短路に沿って目一杯流す
		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}
		f -= d;
		res += (d * h[t]);
		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}
	}

	return res;

}

int main() {
	
	cin >> V >> E >> F;

	for (int i = 0; i < E; i++) {
		int u, v, cap, cost;
		cin >> u >> v >> cap >> cost;
		add_edge(u, v, cap, cost);
	}


	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50104
final_rank: 14

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <functional>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <cmath>
#include<sstream>
#include<list>
#include<iomanip>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <bitset>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int INF = 100000000;
const long long LINF = 3e18 + 7;
const int MAX_N = 2000010;
const int MAX_W = 10002;
const int MAX_ARRAYK = 100000;
double PI = 3.14159265358979323846;
//using ll = long long;

// Minimum Cost Flow (Bellman Ford)
// https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_6_B&lang=ja
// 蟻本 p. 200
// 始点0, 終点V-1

int V, E, F;
struct edge { int to, cap, cost, rev; };

vector<edge> G[MAX_N];
int dist[MAX_N];
int prevv[MAX_N], preve[MAX_N];

// from からtoへ向かう容量cap, コストcostの辺をグラフに追加する
void add_edge(int from, int to, int cap, int cost) {
	edge e1 = { to, cap, cost, G[to].size() };
	G[from].push_back(e1);
	edge e2 = { from, 0, -cost, G[from].size() - 1 };
	G[to].push_back(e2);

}

// sからtへの流量f最小費用流を求める
// 流せない場合は-1を返す
int min_cost_flow(int s, int t, int f) {
	int res = 0;
	while (f > 0) {
		//ベルマンフォードにより、s-t間最短路を求める
		fill(dist, dist + V, INF);
		dist[s] = 0;
		bool update = true;
		while (update) {
			update = false;
			for (int v = 0; v < V; v++) {
				if (dist[v] == INF) {
					continue;
				}
				for (int i = 0; i < G[v].size(); i++) {
					edge& e = G[v][i];
					if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
						dist[e.to] = dist[v] + e.cost;
						prevv[e.to] = v;
						preve[e.to] = i;
						update = true;
					}
				}
			}
		}
		if (dist[t] == INF) {
			return -1;
		}

		// s-t間最短路に沿って目一杯流す。
		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}

		f -= d;
		res += (d * dist[t]);
		for (int v = t; v != s; v = prevv[v]) {
			edge& e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}
	}

	return res;

}

int main() {
	
	cin >> V >> E >> F;

	for (int i = 0; i < E; i++) {
		int u, v, cap, cost;
		cin >> u >> v >> cap >> cost;
		add_edge(u, v, cap, cost);
	}


	cout << min_cost_flow(0, V - 1, F) << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 50084
final_rank: 10