#include #include #include #include #include struct IO { static const int bufsize=1<<24; char ibuf[bufsize], obuf[bufsize]; char *ip, *op; IO(): ip(ibuf), op(obuf) { for(int t = 0, k = 0; (k = read(STDIN_FILENO, ibuf+t, sizeof(ibuf)-t)) > 0; t+=k); } ~IO(){ for(int t = 0, k = 0; (k = write(STDOUT_FILENO, obuf+t, op-obuf-t)) > 0; t+=k); } long long scan_int(){ long long x=0; bool neg=false; for(;*ip<'+';ip++) ; if(*ip=='-'){ neg=true; ip++;} else if(*ip=='+') ip++; for(;*ip>='0';ip++) x = 10*x+*ip-'0'; if(neg) x = -x; return x; } void put_int(long long x, char c=0){ static char tmp[20]; if(x==0) *op++ = '0'; else { int i; if(x<0){ *op++ = '-'; x = -x; } for(i=0; x; i++){ tmp[i] = x % 10; x /= 10; } for(i--; i>=0; i--) *op++ = tmp[i]+'0'; } if(c) *op++ = c; } void put_double(double x, char c=0){ unsigned y; const int mask = (1<<24) - 1; put_int(x); *op++ = '.'; x = x - (int) x; if(x < 0) x = -x; y = x * (1<<24); for(int i=0;i<7;i++){ y *= 10; *op++ = '0' + (y>>24); y &= mask; } if(c) *op++ = c; } inline char scan_char(){ return *ip++; } inline void put_char(char c){ *op++ = c; } inline char *scan_string(){ char *s = ip; while(*ip!='\n'&&*ip!=' ') ip++; *ip++='\0'; return s;} inline void put_string(const char *s, char c=0){ while(*s) *op++=*s++; if(c) *op++=c;} } io; using s32 = int; using u32 = unsigned int; using s64 = long long int; using u64 = unsigned long long int; template class RadixHeap { private: using P = std::pair; u64 last; int size; std::vector

A[65]; int clz(u64 x){ if(x==0) return 64; else return __builtin_clzll(x); } public: RadixHeap(): last(0), size(0) {} bool empty() const { return size == 0; } void push(u64 a, const T &b){ A[clz(last^a)].emplace_back(P(a, b)); size++; } P pop() { if(A[64].empty()){ int i; for(i=63;i>=0 && A[i].empty();i--) ; last = std::min_element(A[i].begin(), A[i].end(), [](P &x, P &y){ return x.first < y.first; })->first; for(auto it = A[i].cbegin(); it != A[i].cend(); ++it){ A[clz(last^it->first)].push_back(*it); } A[i].clear(); } P x = A[64].back(); A[64].pop_back(); size--; return x; } }; u64 norm(s32 x, s32 y){ return std::sqrt((s64) x * x + (s64) y * y) * (1ULL << 32); } int n, m, x, y; std::vector > > edges; std::vector > pq; std::vector lb; int main(){ n = io.scan_int(); m = io.scan_int(); x = io.scan_int()-1; y = io.scan_int()-1; pq.reserve(n); for(int i = 0; i < n; i ++){ s32 p = io.scan_int(); s32 q = io.scan_int(); pq.emplace_back(p, q); } edges.resize(n); for(int i = 0; i < m; i ++){ int p = io.scan_int()-1; int q = io.scan_int()-1; u64 d = norm(pq[p].first - pq[q].first, pq[p].second - pq[q].second); edges[p].emplace_back(q, d); edges[q].emplace_back(p, d); } lb.reserve(n); for(int i = 0; i < n; i ++){ lb.push_back(norm(pq[i].first - pq[y].first, pq[i].second - pq[y].second)); } RadixHeap > queue; constexpr u64 maxd = (1ULL << 63) - 1; std::vector dist(n, maxd); queue.push(lb[x], {x, 0}); dist[x] = 0; while(!queue.empty()){ auto [v, d] = queue.pop().second; if(dist[v] < d) continue; if(v == y) break; for(auto e: edges[v]){ int w = e.first; u64 c = e.second; if(d + c < dist[w]){ dist[w] = d + c; queue.push(d + c + lb[w], {w, d + c}); } } } io.put_double((double) dist[y] / (1ULL << 32), '\n'); return 0; }