← Home
package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
)

const INF int64 = 1 << 60

type DEdge struct {
	to  int
	rev int
	cap int64
}

type Dinic struct {
	n     int
	g     [][]DEdge
	level []int
	it    []int
}

func NewDinic(n int) *Dinic {
	return &Dinic{
		n:     n,
		g:     make([][]DEdge, n),
		level: make([]int, n),
		it:    make([]int, n),
	}
}

func (d *Dinic) AddEdge(fr, to int, cap int64) int {
	fi := len(d.g[fr])
	ti := len(d.g[to])
	d.g[fr] = append(d.g[fr], DEdge{to: to, rev: ti, cap: cap})
	d.g[to] = append(d.g[to], DEdge{to: fr, rev: fi, cap: 0})
	return fi
}

func (d *Dinic) bfs(s, t int) bool {
	for i := 0; i < d.n; i++ {
		d.level[i] = -1
	}
	q := make([]int, 0, d.n)
	d.level[s] = 0
	q = append(q, s)
	for h := 0; h < len(q); h++ {
		v := q[h]
		for _, e := range d.g[v] {
			if e.cap > 0 && d.level[e.to] < 0 {
				d.level[e.to] = d.level[v] + 1
				q = append(q, e.to)
			}
		}
	}
	return d.level[t] >= 0
}

func min64(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func (d *Dinic) dfs(v, t int, f int64) int64 {
	if v == t {
		return f
	}
	for ; d.it[v] < len(d.g[v]); d.it[v]++ {
		i := d.it[v]
		e := &d.g[v][i]
		if e.cap > 0 && d.level[v] < d.level[e.to] {
			ret := d.dfs(e.to, t, min64(f, e.cap))
			if ret > 0 {
				e.cap -= ret
				d.g[e.to][e.rev].cap += ret
				return ret
			}
		}
	}
	return 0
}

func (d *Dinic) MaxFlow(s, t int) int64 {
	var flow int64
	for d.bfs(s, t) {
		for i := 0; i < d.n; i++ {
			d.it[i] = 0
		}
		for {
			f := d.dfs(s, t, INF)
			if f == 0 {
				break
			}
			flow += f
		}
	}
	return flow
}

type MEdge struct {
	to   int
	rev  int
	cap  int64
	cost int64
}

type MCMF struct {
	n int
	g [][]MEdge
}

func NewMCMF(n int) *MCMF {
	return &MCMF{
		n: n,
		g: make([][]MEdge, n),
	}
}

func (m *MCMF) AddEdge(fr, to int, cap, cost int64) {
	fi := len(m.g[fr])
	ti := len(m.g[to])
	m.g[fr] = append(m.g[fr], MEdge{to: to, rev: ti, cap: cap, cost: cost})
	m.g[to] = append(m.g[to], MEdge{to: fr, rev: fi, cap: 0, cost: -cost})
}

func (m *MCMF) AddEdgeResidual(fr, to int, fcap, rcap, cost int64) {
	fi := len(m.g[fr])
	ti := len(m.g[to])
	m.g[fr] = append(m.g[fr], MEdge{to: to, rev: ti, cap: fcap, cost: cost})
	m.g[to] = append(m.g[to], MEdge{to: fr, rev: fi, cap: rcap, cost: -cost})
}

type Item struct {
	d int64
	v int
}

type PQ []Item

func (pq PQ) Len() int { return len(pq) }
func (pq PQ) Less(i, j int) bool {
	return pq[i].d < pq[j].d
}
func (pq PQ) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}
func (pq *PQ) Push(x interface{}) {
	*pq = append(*pq, x.(Item))
}
func (pq *PQ) Pop() interface{} {
	old := *pq
	n := len(old)
	x := old[n-1]
	*pq = old[:n-1]
	return x
}

func (m *MCMF) ShortestPath(s int, pot []int64) ([]int64, []int, []int) {
	dist := make([]int64, m.n)
	pv := make([]int, m.n)
	pe := make([]int, m.n)
	for i := 0; i < m.n; i++ {
		dist[i] = INF
		pv[i] = -1
		pe[i] = -1
	}
	dist[s] = 0
	pq := &PQ{}
	heap.Init(pq)
	heap.Push(pq, Item{d: 0, v: s})
	for pq.Len() > 0 {
		it := heap.Pop(pq).(Item)
		if it.d != dist[it.v] {
			continue
		}
		v := it.v
		for i, e := range m.g[v] {
			if e.cap <= 0 {
				continue
			}
			nd := it.d + e.cost + pot[v] - pot[e.to]
			if nd < dist[e.to] {
				dist[e.to] = nd
				pv[e.to] = v
				pe[e.to] = i
				heap.Push(pq, Item{d: nd, v: e.to})
			}
		}
	}
	return dist, pv, pe
}

func (m *MCMF) Augment(s, t int, pv, pe []int, f int64) {
	for v := t; v != s; v = pv[v] {
		p := pv[v]
		i := pe[v]
		rev := m.g[p][i].rev
		m.g[p][i].cap -= f
		m.g[v][rev].cap += f
	}
}

type Orig struct {
	u   int
	v   int
	cap int64
	idx int
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var n int
	var k int64
	fmt.Fscan(in, &n, &k)

	d := NewDinic(n)
	origs := make([]Orig, 0)

	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			var c int64
			fmt.Fscan(in, &c)
			if c > 0 {
				idx := d.AddEdge(i, j, c)
				origs = append(origs, Orig{u: i, v: j, cap: c, idx: idx})
			}
		}
	}

	base := d.MaxFlow(0, n-1)
	if k == 0 {
		fmt.Fprintln(out, base)
		return
	}

	m := NewMCMF(n)
	for _, e := range origs {
		flow := e.cap - d.g[e.u][e.idx].cap
		m.AddEdgeResidual(e.u, e.v, e.cap-flow, flow, 0)
		m.AddEdge(e.u, e.v, k, 1)
	}

	pot := make([]int64, n)
	var used int64
	var added int64

	for used < k {
		dist, pv, pe := m.ShortestPath(0, pot)
		if dist[n-1] >= INF/2 {
			break
		}

		pathCost := dist[n-1] + pot[n-1] - pot[0]
		for i := 0; i < n; i++ {
			if dist[i] < INF/2 {
				pot[i] += dist[i]
			}
		}

		f := INF
		for v := n - 1; v != 0; v = pv[v] {
			p := pv[v]
			i := pe[v]
			if p < 0 {
				f = 0
				break
			}
			if m.g[p][i].cap < f {
				f = m.g[p][i].cap
			}
		}
		if f == 0 {
			break
		}

		if pathCost > 0 {
			can := (k - used) / pathCost
			if can == 0 {
				break
			}
			if f > can {
				f = can
			}
			used += f * pathCost
		}

		m.Augment(0, n-1, pv, pe, f)
		added += f
	}

	fmt.Fprintln(out, base+added)
}