diff --git a/algorithms/graph/dinic.cpp b/algorithms/graph/dinic.cpp
index 1403b4436df2d07a64b98e3730598bf8739467ee..fb65287d7ff7d164b87f978ee293830d9047dd3b 100644
--- a/algorithms/graph/dinic.cpp
+++ b/algorithms/graph/dinic.cpp
@@ -15,11 +15,11 @@ struct Dinic {
   Dinic(int N) : 
     N(N), depth(N), start(N), graph(N) {}
 
-  void add_edge(int s, int t, int c) {
-    Edge forw = { t, 0, c, (int) graph[t].size() };
-    Edge back = { s, 0, 0, (int) graph[s].size() };
-    graph[s].pb(forw);
-    graph[t].pb(back);
+  void add_edge(int u, int v, int c) {
+    Edge forw = { v, 0, c, (int) graph[v].size() };
+    Edge back = { u, 0, 0, (int) graph[u].size() };
+    graph[u].pb(forw);
+    graph[v].pb(back);
   }
 
   bool bfs(int s, int t) {
diff --git a/algorithms/graph/min_cost_max_flow.cpp b/algorithms/graph/min_cost_max_flow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ff37950aedc271abe87842c3cfa663bb76371ef4
--- /dev/null
+++ b/algorithms/graph/min_cost_max_flow.cpp
@@ -0,0 +1,79 @@
+/// Minimum Cost Maximum Flow
+///
+/// Time: O(V^2 * E)
+/// Space: O(V + E)
+  
+struct MinCostMaxFlow {
+  struct Edge { int u, v, cap, cost; };
+
+  int N;
+  vector<Edge> edges;
+  vector<vector<int>> adj;
+  vector<int> vis, dist, par, ind;
+
+  MinCostMaxFlow(int N) :
+    N(N), vis(N), dist(N), par(N), ind(N), adj(N) {}
+
+  void add_edge(int u, int v, int cap, int cost) {
+    adj[u].pb(edges.size());
+    edges.pb({ u, v, cap, cost });
+
+    adj[v].pb(edges.size());
+    edges.pb({ v, u, 0, -cost });
+  }
+
+  // Shortest Path Faster Algorithm (slower than 
+  // Dijkstra but works with negative edges).
+  bool spfa(int s, int t) {
+    fill(all(dist), inf);
+    dist[s] = 0;
+
+    queue<int> Q;
+    Q.push(s);
+
+    while (!Q.empty()) {
+      int u = Q.front(); Q.pop();
+      vis[u] = 0;
+
+      for (auto i : adj[u]) {
+        Edge &e = edges[i];
+        int v = e.v;
+
+        if (e.cap > 0 && dist[v] > dist[u] + e.cost) {
+          dist[v] = dist[u] + e.cost;
+          par[v] = u;
+          ind[v] = i;
+
+          if (!vis[v]) {
+            Q.push(v);
+            vis[v] = 1;
+          }
+        }
+      }
+    }
+
+    return dist[t] < inf;
+  }
+
+  // Returns pair (min_cost, max_flow).
+  ii run(int s, int t) {
+    int min_cost = 0;
+    int max_flow = 0;
+
+    while (spfa(s, t)) {
+      int flow = inf;
+      for (int i = t; i != s; i = par[i])
+        flow = min(flow, edges[ind[i]].cap);
+      
+      for (int i = t; i != s; i = par[i]) {
+        edges[ind[i]  ].cap -= flow;
+        edges[ind[i]^1].cap += flow;
+      }
+
+      min_cost += flow * dist[t];
+      max_flow += flow;
+    }
+
+    return ii(min_cost, max_flow);
+  }
+};
diff --git a/caderno.pdf b/caderno.pdf
index 05adf703638921726f8fe8b69b23750388d1f202..3ae532569df79b62bfa711e4c399d821fab6ba0d 100644
Binary files a/caderno.pdf and b/caderno.pdf differ
diff --git a/contests/Cadernaveis/UVA10594.cpp b/contests/Cadernaveis/UVA10594.cpp
index 8a5b115e381cc538ffaf056ff7edee7eb68d4cd9..c0794ea984ade55b6a9fd3af58ad0232ada97027 100644
--- a/contests/Cadernaveis/UVA10594.cpp
+++ b/contests/Cadernaveis/UVA10594.cpp
@@ -1,5 +1,7 @@
 #include <bits/stdc++.h>
 
+#define MAXN 110
+#define MAXM 20010
 #define EPS 1e-6
 #define MOD 1000000007
 #define inf 0x3f3f3f3f
@@ -16,63 +18,82 @@
 
 using namespace std; 
 
-typedef long long ll;
-typedef pair<int,int> ii;
+using ll = long long;
+using ii = pair<int,int>;
 
-int N;
-int par[MAX];
-int graph[MAX][MAX], rg[MAX][MAX];
+struct MinCostMaxFlow {
+  struct Edge {
+    int u, v, cap, cost;
+  };
 
-bool cont[MAX];
+  int N;
+  vector<Edge> edges;
+  vector<vector<int>> adj;
+  vector<int> vis, dist, par, ind;
 
+  MinCostMaxFlow(int N) :
+    N(N), vis(N), dist(N), par(N), ind(N), adj(N) {}
 
-bool bfs(int s, int t) {
-  queue<int> Q;
-  Q.push(s);
-  cont[s] = true;
+  void add_edge(int u, int v, int cap, int cost) {
+    adj[u].pb(edges.size());
+    edges.pb({ u, v, cap, cost });
 
-  while (!Q.empty()) {
-    int u = Q.front(); Q.pop();
-
-    // Sink was found, there is a path
-    if (u == t)
-      return true;
-
-    for (int i = 0; i < N; ++i)
-      if (!cont[i] && rg[u][i]) {
-        cont[i] = true;
-        par[i] = u;
-        Q.push(i);
-      }
+    adj[v].pb(edges.size());
+    edges.pb({ v, u, 0, -cost });
   }
 
-  return false;
-}
+  bool spfa(int s, int t) {
+    fill(all(dist), inf);
+    dist[s] = 0;
 
-int edmonds_karp(int s, int t) {
-  int ans = 0;
-  par[s] = -1;
+    queue<int> Q;
+    Q.push(s);
 
-  mset(cont, 0);
-  memcpy(rg, graph, sizeof(graph));
+    while (!Q.empty()) {
+      int u = Q.front(); Q.pop();
+      vis[u] = 0;
 
-  while (bfs(s, t)) {
-    int flow = inf;
+      for (auto i : adj[u]) {
+        Edge &e = edges[i];
+        int v = e.v;
 
-    for (int i = t; par[i] != -1; i = par[i])
-      flow = min(flow, rg[par[i]][i]);
+        if (e.cap > 0 && dist[v] > dist[u] + e.cost) {
+          dist[v] = dist[u] + e.cost;
+          par[v] = u;
+          ind[v] = i;
 
-    for (int i = t; par[i] != -1; i = par[i]) {
-      rg[par[i]][i] -= flow;
-      rg[i][par[i]] += flow;
+          if (!vis[v]) {
+            Q.push(v);
+            vis[v] = 1;
+          }
+        }
+      }
     }
 
-    ans += flow;
-    mset(cont, 0);
+    return dist[t] < inf;
   }
 
-  return ans;
-}
+  pair<ll,int> run(int s, int t) {
+    ll mincost = 0;
+    int maxflow = 0;
+
+    while (spfa(s, t)) {
+      ll flow = inf;
+      for (int i = t; i != s; i = par[i])
+        flow = min(flow, (ll) edges[ind[i]].cap);
+      
+      for (int i = t; i != s; i = par[i]) {
+        edges[ind[i]  ].cap -= flow;
+        edges[ind[i]^1].cap += flow;
+      }
+
+      mincost += flow * dist[t];
+      maxflow += flow;
+    }
+
+    return make_pair(mincost, maxflow);
+  }
+};
 
 int main() {
   ios::sync_with_stdio(0);
@@ -80,10 +101,23 @@ int main() {
 
   int n, m;
   while (cin >> n >> m) {
+    MinCostMaxFlow mcmf(110);
+
+    vector<pair<ii,int>> aux(m);
+    for (int i = 0; i < m; ++i)
+      cin >> aux[i].fi.fi >> aux[i].fi.se >> aux[i].se;
+
+    int d, k; cin >> d >> k;
+    mcmf.add_edge(0, 1, d, 0);
     for (int i = 0; i < m; ++i) {
-      int a, b, c; cin >> a >> b >> c;
-      
+      mcmf.add_edge(aux[i].fi.fi, aux[i].fi.se, k, aux[i].se);
+      mcmf.add_edge(aux[i].fi.se, aux[i].fi.fi, k, aux[i].se);
     }
+
+    pair<ll,int> ans = mcmf.run(0, n);
+
+    if (ans.se != d) cout << "Impossible." << ende;
+    else cout << ans.fi << ende;
   }
 
   return 0;
diff --git a/contests/Cadernaveis/in b/contests/Cadernaveis/in
deleted file mode 100644
index 7fe77f6847af1c61e722fd515fb19ab9b3007682..0000000000000000000000000000000000000000
--- a/contests/Cadernaveis/in
+++ /dev/null
@@ -1,20 +0,0 @@
-2
-0 0 0 0 6 9 8 3 0
-9 8 0 0 0 0 0 7 6
-6 0 0 0 3 8 0 5 1
-2 0 5 0 8 1 0 9 0
-0 6 0 0 0 0 0 8 0
-0 9 0 3 7 0 6 0 2
-3 4 0 8 5 0 0 0 9
-7 2 0 0 0 0 0 6 8
-0 5 6 9 2 0 0 0 0
-
-0 0 0 0 6 9 8 3 0
-9 8 0 0 0 0 0 7 6
-6 0 0 0 3 8 0 5 1
-2 0 5 4 8 1 0 9 0
-0 6 0 0 0 0 0 8 0
-0 9 0 3 7 0 6 0 2
-3 4 0 8 5 0 0 0 9
-7 2 0 0 0 0 0 6 8
-0 5 6 9 2 0 0 0 0