#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define Pr pair<ll, ll>
#define Tp tuple<int, int, int>
using Graph = vector<vector<int>>;

vector<int> col;
vector<int> ans;
vector<int> col2;
// dfs
// s:始点 i:dfs回数 t:始点からの距離
vector<int> vis;
void dfs(Graph &G, int s, int i) {
    if (col[col2[s]] == 0)
        ans.push_back(s);
    col[col2[s]]++;
    for (int nx : G[s]) {
        if (vis[nx] == i)
            continue;
        vis[nx] = i;
        dfs(G, nx, i);
    }
    col[col2[s]]--;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N;
    cin >> N;
    col.assign(100001, 0);
    col2.assign(N + 1, 0);
    rep(i, N) { cin >> col2[i + 1]; }
    Graph G(N + 1);
    rep(i, N - 1) {
        int a, b;
        cin >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    // main関数内で
    vis.assign(N + 1, -1);
    vis[1] = 0;
    dfs(G, 1, 0); // s:始点 i:dfs回数
    sort(ans.begin(), ans.end());
    rep(i, ans.size()) { cout << ans[i] << "\n"; }
}
#include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
using vb = vector<bool>;
using vl = vector<long>;
using vs = vector<string>;
using vvi = vector<vector<int>>;
using vvb = vector<vector<bool>>;
using vvc = vector<vector<char>>;
using vvl = vector<vector<long>>;
using pii = pair<int, int>;
using pil = pair<int, long>;
using pll = pair<long, long>;
#define fix20 cout << fixed << setprecision(20)
#define YES cout << "Yes" << endl
#define NO cout << "No" << endl
#define rep(i,n) for(long i=0; i<(long)(n);i++)
#define REP(i,s,t) for(long i=s; i<t; i++)
#define RNG(i,s,t,u) for(long i=s; i<t; i+=u)
#define MOD 998244353
#define all(vec) vec.begin(), vec.end()
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }


void Initpar(long n, vl &par){
  //par = vector<int>(n); 
  for(long i=0; i<n; i++) par.at(i) = i;
}

int root(long x, vl &par){
  if(x == par.at(x)) return x;
  else return par.at(x) = root(par.at(x), par);
}

void unite(long x, long y, vl &par){
  long rx = root(x, par);
  long ry = root(y ,par);
  if(rx == ry) return ;
  if(rx < ry) par.at(ry) = rx;
  else par.at(rx) = ry;
}

bool same(long x, long y, vl &par){
  return root(x, par) == root(y, par);
}

void update_par(vl &par){
  for(long i=0;i<par.size();i++){
    root(i, par);
  }
}

int main(){
  long n,k;
  cin >> n >> k;
  vvl a(n, vl(n));
  rep(i,n){
    rep(j,n) cin >> a.at(i).at(j);
  }
  vl permu(n+300,1);
  REP(i,1,n+300){
    permu.at(i) = permu.at(i-1)*i % MOD;
  }
  long ans = 1;
  vl rpar(n);
  vl cpar(n);
  Initpar(n,rpar);
  Initpar(n,cpar);
  
  rep(i,n){
    REP(j,i+1,n){
      bool flag = true;
      rep(l,n){
        long p = a[i][l] + a[j][l];
        if(p > k){
          flag = false;
          break;
        }
      }
      if(flag){
        unite(i,j,rpar);
      }
    }
  }
  update_par(rpar);
  vl rcnt(n,0);
  rep(i,n){
    rcnt.at(rpar.at(i))++;
  }
  rep(i,n){
    ans = (ans * permu.at(rcnt.at(i))) % MOD;
  }
  
  rep(i,n){
    //cout << "01" << i << endl;
    //cout << n << endl;
    REP(j,i+1,n){
      //cout << i << j << endl;
      bool flag = true;
      rep(l,n){
        long p = a[l][i] + a[l][j];
        //cout << p << endl;
        if(p > k){
          flag = false;
          break;
        }
      }
      if(flag){
        unite(i,j,cpar);
      }
    }
  }
  update_par(cpar);
  //update_par(cpar);
  vl ccnt(n,0);
  rep(i,n){
    ccnt.at(cpar.at(i))++;
  }
  rep(i,n){
    ans = (ans * permu.at(ccnt.at(i))) % MOD;
  }
  cout << ans << endl;
  if(ans < 0) 3/0;
  //rep(i,n) cout << permu.at(i) << endl;
}