diff --git a/algorithms/graph/dinic.cpp b/algorithms/graph/dinic.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2cadd909ab2c371b19f77884e6b44dd3bd2aadfb
--- /dev/null
+++ b/algorithms/graph/dinic.cpp
@@ -0,0 +1,103 @@
+/**
+ * Dinic's
+ *
+ * Complexity (Time): O(E*V^2)
+ * Complexity (Space): O(V + E)
+ */
+
+// Edge struct to be used in adjacency list similar to vector<ii> graph[MAX], 
+// but storing more information than ii
+typedef struct edge {
+  int u;
+  int flow, cap;
+
+  // Id of the reverse edge on graph[u]
+  int rev;
+
+  edge(int u, int flow, int cap, int rev) :
+    u(u), flow(flow), cap(cap), rev(rev)
+  {}
+} egde;
+
+
+int depth[MAX];
+int start[MAX];
+vector<edge> graph[MAX];
+
+
+// Adds edge between s and t with capacity c
+void add_edge(int s, int t, int c) {
+  edge forward(t, 0, c, graph[t].sz);
+  edge backward(s, 0, 0, graph[s].sz);
+
+  graph[s].pb(forward);
+  graph[t].pb(backward);
+}
+
+
+// Calculates depth of each vertex from source, considering only
+// edges with remaining capacity
+bool bfs(int s, int t) {
+  queue<int> Q;
+  Q.push(s);
+
+  mset(depth, -1);
+  depth[s] = 0;
+
+  while (!Q.empty()) {
+    int v = Q.front(); Q.pop();
+    
+    for (auto i : graph[v]) {
+      if (depth[i.u] == -1 && i.flow < i.cap) {
+        depth[i.u] = depth[v] + 1;
+        Q.push(i.u);
+      }
+    }
+  }
+
+  return depth[t] != -1;
+}
+
+
+// Finds bottleneck flow and add to the edges belonging to the paths found
+int dfs(int s, int t, int flow) {
+  if (s == t)
+    return flow;
+
+  // Start iteration from where it last stopped to avoid repetitions
+  for ( ; start[s] < graph[s].sz; ++start[s]) {
+    edge &e = graph[s][start[s]];
+
+    // If the next vertex is further from the source (and closer to the sink)
+    // and the edge is not at full capacity, then explore it
+    if (depth[e.u] == depth[s] + 1 && e.flow < e.cap) {
+      int min_flow = dfs(e.u, t, min(flow, e.cap - e.flow));
+
+      if (min_flow > 0) {
+        e.flow += min_flow;
+        graph[e.u][e.rev].flow -= min_flow;
+        return min_flow;
+      }
+    }
+  }
+
+  return 0;
+}
+
+
+// Returns maximum flow between s and t
+int dinic(int s, int t) {
+  int ans = 0;
+
+  // Run bfs to set depth array (depth of each vertex from source)
+  while (bfs(s, t)) {
+    mset(start, 0);
+
+    // Find every available path from the current depth information,
+    // set the flow of the edges and add the pushed flow to the answer
+    while (int flow = dfs(s, t, inf))
+      ans += flow;
+  }
+
+  return ans;
+}