use std::{collections::BinaryHeap, cmp::Reverse}; const INF: f64 = (1usize << 60) as f64; #[derive(PartialEq, PartialOrd, Clone, Debug)] struct Sortable(T); impl Eq for Sortable {} impl Ord for Sortable { fn cmp(&self, other: &Sortable) -> std::cmp::Ordering { self.0.partial_cmp(&other.0).unwrap() } } fn dijkstra(start: usize, paths: &Vec>) -> Vec { let n = paths.len(); let mut que = BinaryHeap::new(); que.push((Reverse(Sortable(0.)), start)); let mut costs = vec![INF; n]; costs[start] = 0.; while let Some((Reverse(Sortable(cost)), u)) = que.pop() { if cost > costs[u] { continue; } for &(v, w) in paths[u].iter() { if costs[u] + w < costs[v] { costs[v] = costs[u] + w; que.push((Reverse(Sortable(costs[v])), v)); } } } costs } fn calc(a: (isize, isize), b: (isize, isize)) -> f64 { (((a.0 - b.0) as f64).powf(2.) + ((a.1 - b.1) as f64).powf(2.)).sqrt() } fn main() { let mut nm = String::new(); std::io::stdin().read_line(&mut nm).ok(); let nm: Vec = nm.trim().split_whitespace().map(|s| s.parse().unwrap()).collect(); let n = nm[0]; let m = nm[1]; let mut temp = String::new(); std::io::stdin().read_line(&mut temp).ok(); let temp: Vec = temp.trim().split_whitespace().map(|s| s.parse().unwrap()).collect(); let x = temp[0]-1; let y = temp[1]-1; let points = (0..n).map(|_| { let mut temp = String::new(); std::io::stdin().read_line(&mut temp).ok(); let temp: Vec = temp.trim().split_whitespace().map(|s| s.parse().unwrap()).collect(); (temp[0], temp[1]) }) .collect::>(); let mut paths = vec![vec![]; n]; for _ in 0..m { let mut temp = String::new(); std::io::stdin().read_line(&mut temp).ok(); let temp: Vec = temp.trim().split_whitespace().map(|s| s.parse().unwrap()).collect(); let u = temp[0]-1; let v = temp[1]-1; let dist = calc(points[u], points[v]); paths[u].push((v, dist)); paths[v].push((u, dist)); } let dists = dijkstra(x, &paths); println!("{}", dists[y]); }