#include using namespace std; template struct merge_tree { using S = typename Monoid::S; merge_tree(int n) : p(n, -1), d(n, Monoid::e()) {} merge_tree(const vector &v) : p(v.size(), -1), d(v) {} void set(int u, const S &x) { d[u] = x; } int leader(int u) const { return p[u] < 0 ? u : leader(p[u]); } bool same(int u, int v) const { return leader(u) == leader(v); } int size(int u) const { return -p[leader(u)]; } S get(int u) const { return d[leader(u)]; } void merge(int u, int v) { u = leader(u); v = leader(v); if (u == v) return; if (size(u) < size(v)) swap(u, v); p[u] += p[v]; p[v] = u; d[u] = Monoid::op(d[u], d[v]); d[v] = Monoid::e(); } private: vector p; vector d; }; template ::max()> struct max_monoid { using S = T; static S op(const S &a, const S &b) { return max(a, b); } static S e() { return E; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, M, K; cin >> N >> M >> K; vector A(N); for (int i = 0; i < N; i++) cin >> A[i]; vector u(M), v(M); for (int i = 0; i < M; i++) cin >> u[i] >> v[i], u[i]--, v[i]--; vector ord(M); iota(ord.begin(), ord.end(), 0); sort(ord.begin(), ord.end(), [&](int i, int j) { return max(A[u[i]], A[v[i]]) < max(A[u[j]], A[v[j]]); }); merge_tree> uf(N); for (int i = 0; i < N; i++) { uf.set(i, A[i]); } for (int i : ord) { int a = uf.get(u[i]), b = uf.get(v[i]); if (abs(a - b) > K) { cout << "No\n"; return 0; } uf.merge(u[i], v[i]); } cout << "Yes\n"; }