#include <bits/stdc++.h>
using namespace std;
namespace fast_scanner {
static char ibuf[1 << 20], *p1 = ibuf, *p2 = ibuf;
bool advance() { return p2 = (p1 = ibuf) + fread(ibuf, 1, sizeof(ibuf), stdin), (p1 == p2); }
char gc() { return (p1 == p2 && advance()) ? EOF : (*p1++); }
void put_back() { p1--; }
static bool isspace(char c) { return static_cast<unsigned char>(c - '\t') < 5 || c == ' '; }
static bool isdigit(char c) { return static_cast<unsigned char>(c - '0') < 10; }
static inline bool isoneof(char c, const char *str) { return strchr(str, c) != nullptr; }
template <const char *str> static inline bool isoneof(char c) { return strchr(str, c) != nullptr; }
uint64_t read_ull() {
    char ch = gc();
    while (!isdigit(ch)) {
        ch = gc();
    }
    uint64_t res = 0;
    while (isdigit(ch)) {
        res = res * 10 + (ch - '0'), ch = gc();
    }
    return res;
}
int64_t read_ll() {
    char ch = gc();
    bool neg = false;
    while (!isdigit(ch)) {
        neg |= (ch == '-'), ch = gc();
    }
    uint64_t res = 0;
    while (isdigit(ch)) {
        res = res * 10 + (ch - '0'), ch = gc();
    }
    neg && (res = -res);
    return res;
}
long double read_ld() {
    char ch = gc();
    bool neg = false;
    while (!isdigit(ch)) {
        neg |= (ch == '-'), ch = gc();
    }
    uint64_t integerPart = 0, fractionalPart = 0, len = 0, base = 1;
    while (isdigit(ch)) {
        integerPart = integerPart * 10 + (ch - '0'), ch = gc();
    }
    if (ch == '.') {
        ch = gc();
        while (isdigit(ch)) {
            fractionalPart = fractionalPart * 10 + (ch - '0'), ch = gc(), len += 1;
        }
        while (len--)
            base *= 10;
    }
    long double res = (long double)integerPart + (long double)fractionalPart / base;
    neg && (res = -res);
    return res;
}
string read_delim(const char *str) {
    char ch = gc();
    while (isoneof(ch, str))
        ch = gc();
    string res;
    while (!isoneof(ch, str))
        res += ch, ch = gc();
    return res;
}
template <typename UnaryPredicate> string read_delim(UnaryPredicate predicate) {
    char ch = gc();
    while (predicate(ch))
        ch = gc();
    string res;
    while (!predicate(ch))
        res += ch, ch = gc();
    return res;
}
string read_line() {
    return read_delim([](char ch) {
        return ch == '\n';
    });
}
string read_string() { return read_delim(isspace); }
char read_char() { return gc(); }
int read_int() { return (int)read_ll(); }
void skip_whitespace() {
    char ch = gc();
    while (isspace(ch))
        ch = gc();
    put_back();
}
}
template <typename T> T scan();
template <> int scan<int>() { return fast_scanner::read_int(); }
template <> long scan<long>() { return (long)fast_scanner::read_ll(); }
template <> long long scan<long long>() { return fast_scanner::read_ll(); }
template <> long double scan<long double>() { return fast_scanner::read_ld(); }
template <> double scan<double>() { return (double)fast_scanner::read_ld(); }
template <> string scan<string>() { return fast_scanner::read_string(); }
template <> char scan<char>() { return fast_scanner::gc(); }
void scan() { fast_scanner::skip_whitespace(); }
template <typename A, typename B> tuple<A, B> scan() {
    auto a = scan<A>();
    auto b = scan<B>();
    return make_tuple(a, b);
}
template <typename A, typename B, typename C, typename... Args> tuple<A, B, C, Args...> scan() {
    auto a = make_tuple(scan<A>());
    auto b = scan<B, C, Args...>();
    return tuple_cat(a, b);
}
template <typename T, size_t U> array<T, U> scan() {
    array<T, U> res;
    for (int i = 0; i < U; ++i)
        res[i] = scan<T>();
    return res;
}
template <typename T> vector<T> scan(int n) {
    vector<T> res(n);
    for (int i = 0; i < n; ++i) {
        res[i] = scan<T>();
    }
    return res;
}
template <typename T> vector<vector<T>> scan(int n, int m) {
    vector<vector<T>> res(n, vector<T>(m));
    for (int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            res[i][j] = scan<T>();
        }
    }
    return res;
}
vector<vector<char>> scan_cg(int n, int m) {
    vector<vector<char>> res(n, vector<char>(m));
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            res[i][j] = scan<char>();
        }
        scan();
    }
    return res;
}
template<typename A, typename B> vector<pair<A,B>> scan(int n) {
    vector<pair<A, B>> res(n);
    for(int i = 0; i < n; ++i) {
        res[i].first = scan<A>();
        res[i].second = scan<B>();
    }
    return res;
}
template<typename A, typename B, typename C, typename ...Args> vector<tuple<A, B, C, Args...>> scan(int n){
    vector<tuple<A, B,C, Args...>> res(n);
    for(int i = 0; i < n; ++i){
        res[i] = scan<A, B, C, Args...>();
    }
    return res;
}
template <typename T, size_t U> vector<array<T, U>> scan(int n) {
    vector<array<T, U>> res(n);
    for (int i = 0; i < U; ++i)
        res[i] = scan<T, U>();
    return res;
}
template <typename T, size_t X> void ctvl(T (&a)[X], const T &v) { fill_n(&a[0], X, v); }
template <typename T, size_t X, size_t Y> void ctvl2(T (&a)[X][Y], const T &v) { fill_n(&a[0][0], X * Y, v); }
template <typename T, size_t X, size_t Y, size_t Z> void ctvl3(T (&a)[X][Y][Z], const T &v) { fill_n(&a[0][0][0], X * Y * Z, v); }
template <typename T, size_t X, size_t Y, size_t Z, size_t W> void ctvl3(T (&a)[X][Y][Z][W], const T &v) { fill_n(&a[0][0][0][0], X * Y * Z * W, v); }
template <typename T> T read() { T x; cin >> x; return x; }
template <typename... Args> void writeln(const Args &... args) { ((cout << args << " "), ...), cout << endl; }
template <typename... Args> void write(const Args &... args) { ((cout << args), ...); }
template <typename T> typename enable_if<is_same<decltype(declval<T>().size()), size_t>::value, int>::type operator~(const T &ct) { return (int)ct.size(); }
template <typename T, typename... Args> bool ckmax(T &a, const Args &... b) { return (a < max({b...})) ? (a = max({b...}), true) : false; }
template <typename T, typename... Args> bool ckmin(T &a, const Args &... b) { return (a > min({b...})) ? (a = min({b...}), true) : false; }
template <typename T> T div_floor(const T &a, const T &b) { return (a / b) - (!!(a % b) & ((a ^ b) < 0)); }
template <typename T> T div_ceil(const T &a, const T &b) { return (a / b) + (!!(a % b) & ((a ^ b) > 0)); }
template <typename T> using min_heap = priority_queue<T, vector<T>, greater<T>>;
template <typename T> using max_heap = priority_queue<T, vector<T>, less<T>>;
template <typename T, typename... Args, template <typename, typename...> typename Container> Container<T, Args...> &operator+=(Container<T, Args...> &ct, const T &val) { return ct.push_back(val), ct; }
template <typename T, typename... Args, template <typename, typename...> typename Container> Container<T, Args...> &operator+=(const T &val, Container<T, Args...> &ct) { return ct.push_front(val), ct; }
template <typename T, typename... Args, template <typename, typename...> typename Container> T &operator+(Container<T, Args...> &ct) { return *ct.begin(); }
template <typename T, typename... Args, template <typename, typename...> typename Container> T &operator-(Container<T, Args...> &ct) { return *prev(ct.end()); }
template <typename T, typename... Args, template <typename, typename...> typename Container> T operator--(Container<T, Args...> &ct) { auto res = *ct.begin(); return ct.erase(ct.begin()), res; }
template <typename T, typename... Args, template <typename, typename...> typename Container> T operator--(Container<T, Args...> &ct, int) { auto res = *prev(ct.end()); return ct.erase(prev(ct.end())), res; }
template <typename T, typename... Args, template <typename, typename...> typename Container> int lbi(const Container<T, Args...> &ct, const T &val) { return (int)(lower_bound(ct.begin(), ct.end(), val) - ct.begin()); }
template <typename T, typename... Args, template <typename, typename...> typename Container> int ubi(const Container<T, Args...> &ct, const T &val) { return (int)(upper_bound(ct.begin(), ct.end(), val) - ct.begin()); }
template <int D, typename T> struct vecnd : public vector<vecnd<D - 1, T>> {
    template <typename... Args> vecnd(int n, Args... args) : vector<vecnd<D - 1, T>>(n, vecnd<D - 1, T>(args...)) {}
    void fill(const T &val = T()) {
        for (auto &it : *this)
            it.fill(val);
    }
    bool bounds_check(int i) { return (i >= 0) and (i < (int)this->size()); }
    template <typename... Args> bool bounds_check(int i, Args... args) {
        return (i >= 0) and (i < (int)this->size()) and (this->at(i).bounds_check(args...));
    }
};
template <typename T> struct vecnd<1, T> : public vector<T> {
    vecnd(int n, const T &val = T()) : vector<T>(n, val) {}
    void fill(const T &val = T()) {
        for (auto &it : *this)
            it = val;
    }
    bool bounds_check(int i) { return (i >= 0) and (i < (int)this->size()); }
};
template <typename T> using V = vecnd<1, T>;
template <typename T> using VV = vecnd<2, T>;
template <typename T> using VVV = vecnd<3, T>;
vector<pair<int, int>> dirs = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
vector<pair<int, int>> edirs = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
template <typename K, typename V> pair<K, V> operator+(const pair<K, V> &a, const pair<K, V> &b) { return {a.first + b.first, a.second + b.second}; }
template <typename K, typename V> pair<K, V> operator-(const pair<K, V> &a, const pair<K, V> &b) { return {a.first - b.first, a.second - b.second}; }
template <typename K, typename V> pair<K, V>& operator+=(pair<K, V> &a, const pair<K, V> &b) { return a = a + b; }
template <typename K, typename V> pair<K, V>& operator-=(pair<K, V> &a, const pair<K, V> &b) { return a = a - b; }
template <typename T> struct range { T u, v;
    range(const T &_u, const T &_v) : u(_u), v(_v) {}
    bool has(const T &w) { return (u <= w) and (w < v); }
    bool has_incl(const T &w) { return (u <= w) and (w <= v); }
};
int log2_floor(uint32_t n) { return 31 - __builtin_clz(n); }
int log2_ceil(uint32_t n) { return log2_floor(n) + !!(n & (n - 1)); }
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T> using vv = vector<vector<T>>;
const int N = 200'010;
auto dfs_tree(int root, const vector<vector<int>>& g) {
    stack<int> h;
    h.push(root);
    int n = g.size();
    vector<int> dist(n), pi(n, -1);
    while(!h.empty()) {
        int u = h.top();
        h.pop();
        for(auto v : g[u]) {
            if(pi[u] != v) {
                pi[v] = u;
                h.push(v);
                assert(dist[v] == 0);
                dist[v] = dist[u] + 1;
            }
        }
    }
    return make_tuple(dist, pi);
}
auto soln() {
    auto [n, k] = scan<int, int>();
    vector<pair<int, int> > edge(n - 1);
    vector<vector<int>> g(n + 1);
    for (int i = 0; i < (int)(n - 1); ++i) {
        auto [u, v] = scan<int, int>();
        edge[i] = make_pair(u, v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    int res = N;
    if (k % 2) {
        for (auto &[u, v] : edge) {
            int count = 0;
            auto [distu, _1] = dfs_tree(u, g);
            auto [distv, _2] = dfs_tree(v, g);
            for (int i = 1; i <= n; ++i) {
                ckmin(distu[i], distv[i]);
                count += (distu[i] > k / 2);
            }
            ckmin(res, count);
        }
    }
    else {
        for (int i = 1; i <= n; ++i) {
            int count = 0;
            auto [dist, _3] = dfs_tree(i, g);
            ;;
            for (int j = 1; j <= n; ++j) {
                count += (dist[j] > k / 2);
            }
            ckmin(res, count);
        }
    }
    cout << res << "\n";
}
signed main() {
    int t = 1;
    ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
    while (t--)
        soln();
    return 0;
}


Measured memory_bytes: 3860