//#define ACM_LOCAL 1
#if 1

#include<bits/stdc++.h>

#ifdef ONLINE_JUDGE
#define endl '\n'
#endif
using namespace std;
typedef long long ll;
const ll mod(998244353);
const ll MAXN(2e7 + 7);
const double eps(1e-6);

inline ll powmod(ll a, ll b) {
    ll res = 1;
    a %= mod;
    assert(b >= 0);
    for (; b; b >>= 1) {
        if (b & 1)res = res * a % mod;
        a = a * a % mod;
    }
    return res % mod;
}

inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }

struct GlobalData {
    int n, k;
    vector<vector<int>> edges;
    ll ans;

    void addEdge(int u, int v) {
        edges[u].emplace_back(v);
    }

public:
    void init() {
        n = k = ans = 0;
        edges.clear();
    }

    void input() {
        cin >> n >> k;
        edges = vector<vector<int>>(n + 1);
        for (int i = 1; i < n; i++) {
            int u, v;
            cin >> u >> v;
            addEdge(u, v);
            addEdge(v, u);
        }
    }

    void outputAns() {
        cout << ans << endl;
    }

    void preSolve() {}
} globalData;

inline void preSolve() {
    globalData.preSolve();
}

inline void input() {
    globalData.init();
    globalData.input();
}

inline void output() {
    globalData.outputAns();
}

void countSubAns(vector<int> &subAns, vector<int> &prefSubAns, const int &k, int u, int parent) {
    //  [预处理]
    //  从stPoint开始dfs:
    //      [subAns[i]记录子树子节点到根节点最大边距离为i的合法答案情况数量]
    //      初始化 subAns[u][0] = 1
    //      遍历每条边(连接的不是父节点):
    //          递归子树
    //          若删除该边:
    //              subAns[u][j] *= prefSubAns[it][k]
    //          若不删除该边:(j>0)
    //              subAns[u][j] = subAns[u][j]*prefSubAns[it][min(j,k-j)-1] + prefSubAns[u][min(j-1,k-j)]*subAns[it][j-1]
    //          结合： subAns[u][j] = subAns[u][j]*(prefSubAns[it][k]+prefSubAns[it][min(j-1,k-j)]) + prefSubAns[u][min(j-1,k-j)]*subAns[it][j-1]
    //      prefSubAns前缀和数组记录和
    // 特判:  叶子节点
    // BUG1：未删除不合法情况

    subAns[0] = 1;

    for (auto &it: globalData.edges[u]) {
        if (it == parent) continue;
        vector<int> subAnsit(k + 1);
        vector<int> prefSubAnsit(k + 1, 1);
        countSubAns(subAnsit, prefSubAnsit, k, it, u);
        subAns[0] = 1ll * subAns[0] * prefSubAnsit[k] % mod;
        for (int j = 1; j < k; j++) {   // 需要prefSubAns[u][j-1]，故不能马上更新prefSubAns
            subAns[j] = ( 1ll * subAns[j] * (1ll * prefSubAnsit[k] + prefSubAnsit[min(j, k - j) - 1]) % mod +
                         1ll * prefSubAns[min(j - 1, k - j)] * subAnsit[j - 1] % mod) % mod;
        }
        if (k) subAns[k] = (1ll * subAns[k] * prefSubAnsit[k] % mod + 1ll * prefSubAns[0] * subAnsit[k - 1] % mod) % mod;
        prefSubAns[0] = subAns[0];
        for (int j = 1; j <= k; j++) {
            prefSubAns[j] = (1ll * prefSubAns[j - 1] + subAns[j]) % mod;
        }
    }
}

inline void solve() {

    int stPoint = 1;
    vector<int> subAns(globalData.k + 1);
    vector<int> prefSubAns(globalData.k + 1, 1);

    int k = globalData.k;
    countSubAns(subAns, prefSubAns, k, stPoint, 0);
    globalData.ans = prefSubAns[k];

}

int main() {

#ifdef ACM_LOCAL
    freopen("./data/9.in", "r", stdin);
    freopen("./data/9.out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    preSolve();
    int T = 1;
//    cin >> T;
    while (T--) {
        input();
        solve();
        output();
    }

    return 0;

}

#endif