#include #include #include #include struct disjoint_set { std::vector p, r; disjoint_set(unsigned n): p(n), r(n) { for (unsigned i = 0; i < n; ++i) { p[i] = i; r[i] = 0; } } unsigned get(unsigned i) { unsigned root = i; while (p[root] != root) { root = p[root]; } while (i != root) { unsigned pi = p[i]; p[i] = root; i = pi; } return root; } void unite(unsigned a, unsigned b) { a = get(a); b = get(b); if (a != b) { if (r[a] == r[b]) ++r[a]; if (r[a] < r[b]) p[a] = b; else p[b] = a; } } }; struct edge { unsigned a, b, h; bool operator < (edge const &that) const { return h < that.h; } }; int main() { // read header and heights unsigned n, m; scanf("%u%u", &n, &m); std::vector h(n); for (unsigned i = 0; i < n; ++i) { scanf("%u", &h[i]); } // compute unique sorted heights std::vector uniq_h = h; std::sort(uniq_h.begin(), uniq_h.end()); uniq_h.erase(std::unique(uniq_h.begin(), uniq_h.end()), uniq_h.end()); // read edges and partition then by their minimum height std::vector> edges_by_lowest(uniq_h.size()); for (unsigned i = 0; i < m; ++i) { edge e; scanf("%u%u", &e.a, &e.b); --e.a; --e.b; e.h = std::max(h[e.a], h[e.b]); unsigned min_h = std::min(h[e.a], h[e.b]); unsigned idx = std::lower_bound(uniq_h.begin(), uniq_h.end(), min_h) - uniq_h.begin(); edges_by_lowest[idx].push_back(e); } // store the answer unsigned answer = 1000001; // iterate over lower bounds top to bottom std::vector current_edges; for (unsigned lower_p1 = uniq_h.size(); lower_p1; --lower_p1) { // insert new edges into the set; has to be done always std::vector const &new_edges = edges_by_lowest[lower_p1 - 1]; current_edges.insert(current_edges.end(), new_edges.begin(), new_edges.end()); // not reached start/finish with the lower bound yet unsigned curr_h = uniq_h[lower_p1 - 1]; if (curr_h > std::max(h[0], h[1])) { continue; } // sort edges by their maximum height; bottleneck! std::sort(current_edges.begin(), current_edges.end()); // merge in the edges until 0 and 1 are in the same component disjoint_set ds(n); for (edge const &e : current_edges) { unsigned dh = e.h - curr_h; if (dh >= answer) { // cannot improve the answer anymore break; } ds.unite(e.a, e.b); if (ds.get(0) == ds.get(1)) { answer = dh; break; } } } printf("%u\n", answer); return 0; }