#include #include #include #include using namespace std; class UnionFind { public: vector par, rank, siz; int cnt; UnionFind(int n) { par.assign(n, -1); rank.assign(n, 0); siz.assign(n, 1); cnt = n; } int root(int x) { if (par[x] == -1) return x; return par[x] = root(par[x]); } bool issame(int x, int y) { return root(x) == root(y); } bool unite(int x, int y) { int px = root(x); int py = root(y); if (px == py) return false; if (rank[px] < rank[py]) swap(px, py); par[py] = px; if (rank[px] == rank[py]) rank[px]++; siz[px] += siz[py]; cnt--; return false; } int count() { return cnt; } int size(int x) { return siz[root(x)]; } }; 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]; } // G[u] = {(A[v], v)} vector>> G(N); for (int i = 0; i < M; ++i) { int u, v; cin >> u >> v; --u; --v; G[u].emplace_back(A[v], v); G[v].emplace_back(A[u], u); } UnionFind UF(N); vector> dp; for (int i = 0; i < N; ++i) { dp.emplace_back(A[i], i); } // Pythonの dp.sort(reverse=True) sort(dp.rbegin(), dp.rend()); while (dp.size() > 1) { auto [a, i] = dp.back(); dp.pop_back(); int ri = UF.root(i); // G[ri] をヒープとして扱うために make_heap を使う auto& gi = G[ri]; make_heap(gi.begin(), gi.end(), greater<>()); if (gi.empty()) continue; pop_heap(gi.begin(), gi.end(), greater<>()); auto [s, j] = gi.back(); gi.pop_back(); int rj = UF.root(j); if (s - a > K) { cout << "No\n"; return 0; } UF.unite(i, j); int r = UF.root(i); if (G[ri].size() < G[rj].size()) { auto& gj = G[rj]; make_heap(gj.begin(), gj.end(), greater<>()); if (!gj.empty()) { pop_heap(gj.begin(), gj.end(), greater<>()); gj.pop_back(); } for (auto& g : G[ri]) { G[rj].push_back(g); } G[ri].clear(); G[r] = G[rj]; } else { for (auto& g : G[rj]) { if (UF.root(g.second) == ri) continue; G[ri].push_back(g); } G[rj].clear(); G[r] = G[ri]; } } cout << "Yes\n"; return 0; }