Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Maximum Flow

A flow network is a directed graph which has a $source$ and a $sink$. In a flow network, each edge $(u, v)$ has a capacity $c(u, v)$. Each edge receives a flow, but the amount of flow on the edge can not exceed the corresponding capacity. Find the maximum flow from the $source$ to the $sink$.

Input

A flow network is given in the following format.

$|V|\;|E|$

$u_0\;v_0\;c_0$

$u_1\;v_1\;c_1$

:

$u_{|E|-1}\;v_{|E|-1}\;c_{|E|-1}$

$|V|$, $|E|$ is the number of vertices and edges 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$ 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$ is the capacity of $i$-th edge.

Output

Print the maximum flow.

Constraints

$2 \leq |V| \leq 100$

$1 \leq |E| \leq 1000$

$0 \leq c_i \leq 10000$

Sample Input 1

4 5
0 1 2
0 2 1
1 2 1
1 3 1
2 3 2

Sample Output 1

3

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using static System.Console;
using static System.Math;

class Program
{
    static void Main()
    {
        var VE = ReadLine().Split().Select(int.Parse).ToArray();
        var f = new Dinic(VE[0]);
        for (int i = 0; i < VE[1]; i++)
        {
            var line = ReadLine().Split().Select(int.Parse).ToArray();
            f.AddEdge(line[0],line[1],line[2]);
        }
        WriteLine(f.MaxFlow(0,VE[0]-1));
    }
}

class FEdge
{
    public int to;
    public int capacity;
    public int reverse;
}

public class Dinic
{
    List<FEdge>[] graph;
    int[] level;
    int[] iter;

    public Dinic(int V)
    {
        graph = new List<FEdge>[V];
        for (int i = 0; i < V; i++)
        {
            graph[i] = new List<FEdge>();
        }
        level = new int[V];
        iter = new int[V];
    }

    public void AddEdge(int from, int to, int capacity)
    {
        graph[from].Add(new FEdge { to = to, capacity = capacity, reverse = graph[to].Count });
        graph[to].Add(new FEdge { to = from, reverse = graph[from].Count - 1 });
    }

    void BFS(int s)
    {
        for (int i = 0; i < level.Length; i++)
        {
            level[i] = -1;
        }
        var q = new Queue<int>();
        level[s] = 0;
        q.Enqueue(s);
        while (q.Count != 0)
        {
            var v = q.Dequeue();
            for (int i = 0; i < graph[v].Count; i++)
            {
                var e = graph[v][i];
                if (e.capacity > 0 && level[e.to] < 0)
                {
                    level[e.to] = level[v] + 1;
                    q.Enqueue(e.to);
                }
            }
        }
    }

    int DFS(int v, int t, int f)
    {
        if (v == t) return f;
        while(iter[v]<graph[v].Count)//for (ref int i = ref iter[v]; i < graph[v].Count; i++)
        {
            var e = graph[v][iter[v]];//var e = graph[v][i];
            if (e.capacity > 0 && level[v] < level[e.to])
            {
                var d = DFS(e.to, t, Math.Min(f, e.capacity));
                if (d > 0)
                {
                    e.capacity -= d;
                    graph[e.to][e.reverse].capacity += d;
                    return d;
                }
            }
            iter[v]++;//
        }
        return 0;
    }

    public int MaxFlow(int s, int t)
    {
        var flow = 0;
        while (true)
        {
            BFS(s);
            if (level[t] < 0) return flow;
            for (int i = 0; i < iter.Length; i++)
            {
                iter[i] = 0;
            }
            var f = 0;
            while ((f = DFS(s, t, int.MaxValue)) > 0)
            {
                flow += f;
            }
        }
    }
}