#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <functional>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <bitset>
#include <math.h>
#include <random>
#include <chrono>
#include <assert.h>
#include <climits>

using namespace std;
#define int long long

signed main() {
  int n,k;
  cin >> n >> k;
  vector<vector<int>> a(n,vector<int>(n));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      cin >> a[i][j];
    }
  }
  int l = -1, r = 1e9+10;
  while(r - l > 1) {
    // 中央値がmidになると仮定
    int mid = (r + l) / 2;
    // 2次元累積和
    vector<vector<int>> sum(n, vector<int>(n));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (a[i][j] <= mid) sum[i][j] = 1;
        else sum[i][j] = 0;
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = 1; j < n; j++) {
        sum[i][j] += sum[i][j-1];
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = 1; j < n; j++) {
        sum[j][i] += sum[j-1][i];
      }
    }

    bool ok = false;
    for (int i = 0; i + k - 1 < n; i++) {
      for (int j = 0; j + k - 1 < n; j++) {
        int cnt = sum[i+k-1][j+k-1];
        if (i > 0) cnt -= sum[i-1][j+k-1];
        if (j > 0) cnt -= sum[i+k-1][j-1];
        if (i > 0 && j > 0) cnt += sum[i-1][j-1];
        int tot = k*k;

        if (cnt >= tot/2 + (tot%2)) ok = true;
      }
    }
    if (ok) {
      r = mid;
    } else {
      l = mid;
    }
  }
  cout << r << '\n';
}

#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
string to_string(string s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string(string(s)); }
string to_string(bool b) { return to_string(int(b)); }
string to_string(vector<bool>::reference b) { return to_string(int(b)); }
string to_string(char b) { return "'" + string(1, b) + "'"; }
template <typename A, typename B>
string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
template <typename A>
string to_string(A v) {
	string res = "{";
	for (const auto& x : v) res += (res == "{" ? "" : ", ") + to_string(x);
	return res + "}";
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
	cerr << " " << to_string(H);
	debug(T...);
}
#define db(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define db(...) 42
#endif
typedef long long ll;
typedef long double ld;
int main() {
	int n, K;
	scanf("%d%d", &n, &K);
	vector<vector<int>> E(n);
	for (int i = 1; i < n; ++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		--u;
		--v;
		E[u].push_back(v);
		E[v].push_back(u);
	}
	vector<int> depth(n, -1), par(n, -1);
	depth[0] = 0;
	function<void(int)> dfs = [&](int x) {
		for (int y : E[x]) {
			if (depth[y] != -1) continue;
			depth[y] = depth[x] + 1;
			par[y] = x;
			dfs(y);
		}
	};
	dfs(0);
	vector<int> vs(n);
	iota(vs.begin(), vs.end(), 0);
	sort(vs.begin(), vs.end(), [&](int x, int y) {
		return depth[x] > depth[y];
	});
	auto check = [&](int d) {
		vector<int> used(n, -1);
		function<void(int, int, int)> flood = [&](int x, int cur, int p) {
			if (used[x] >= cur) return;
			used[x] = cur;
			if (!cur) return;
			for (int y : E[x]) {
				if (y == p) continue;
				flood(y, cur - 1, x);
			}
		};
		int need = 0;
		for (int v : vs) {
			if (used[v] != -1) continue;
			++need;
			if (need > K) return false;
			int x = v;
			for (int i = 0; i < d; ++i) {
				if (par[x] == -1) break;
				x = par[x];
			}
			flood(x, d, -1);
			assert(used[v] != -1);
		}
		return true;
	};
	int lo = 1, hi = n - 1;
	while (lo < hi) {
		int d = (lo + hi) >> 1;
		if (check(d)) hi = d;
		else lo = d + 1;
	}
	printf("%d\n", lo);
}
