Problem:
Problem E: 街を駆ける道

ネーヴァ王国には、トタタ族とツテテ族、２種類の民族が暮らしている。トタタ族の最大の特徴は、
酢豚にパイナップルを入れて食べることである。だがツテテ族は、パイナップルに酢豚を入れて食べ
る。こんな２つの民族がお互いに仲良くやっていけるはずもなく、トタタ族とツテテ族は、何百年も
の昔からずっといがみ合いを続けてきた。

そんなある日、ネーヴァ王のもとに、２つの民族から嘆願書が届いた。それによるとトタタ族は、自
分たちが暮らす街Ａと街Ｂのあいだを結ぶ道を建設してほしいらしい。一方でツテテ族も、自分たち
が暮らす街Ｃと街Ｄのあいだを結ぶ道を建設してほしいらしい。

２つの民族が衝突するのを防ぐため、トタタ族が通る道とツテテ族が通る道を交差させることはでき
ない。また、技術的な制約により、２つの街のあいだを一直線に結ぶような道しか建設することはで
きない。つまり、必要ならば街Ａと街Ｂを直接道で結ばずに、いくつかのトタタ族の街を経由して街
Ａと街Ｂを間接的に結ぶことになるだろう（もちろん、ツテテ族の街を経由してはならない）。その
際、トタタ族の街を結ぶ道どうしは交差していてもよい。街Ｃと街Ｄについても同様である。

道を建設するには、その長さに比例したコストがかかる。なので、条件をみたしつつ、できるだけ建
設する道の長さの合計が短くなるようにしたい。さて、長さの最小値はいくつになるだろうか。

Input

NA NB

xA,1 yA,1

xA,2 yA,2

.

.

.

xA,NA yA,NA

xB,1 yB,1

xB,2 yB,2

.

.

.

xB,NB yB,NB

入力の１行目には、整数NA（2 ≤ NA ≤ 1,000）と整数NB（2 ≤ NB ≤ 1,000）が、空白区切りで書かれている。これは、ネーヴァ王国にはトタタ族が暮らす街がNA 個、ツテテ族が暮らす街がNB 個あることをあらわす。初期状態では、どこにも道は建設されていない。

続くNA 行には、整数xA,i（-10,000 ≤ xA,i ≤ 10,000）と整数yA,i（-10,000 ≤ yA,i ≤ 10,000）が、空白区切りで書かれている。ネーヴァ王国の地理は２次元直交座標平面であらわされ、１＋ i 行目に書かれた整数xA,i とyA,i は、トタタ族が暮らすi 番目の街の位置座標が(xA,i, yA,i) であることをあらわす。(xA,1, yA,1) と(xA,2, yA,2) が、結ぶべき２つの街の座標である。

続くNB 行には、整数xB,i（-10,000 ≤ xB,i ≤ 10,000）と整数yB,i（-10,000 ≤ yB,i ≤ 10,000）が、空白区切りで書かれている。１＋ NA ＋ i 行目に書かれた整数xB,i とyB,i は、ツテテ族が暮らすi 番目の街の位置座標が(xB,i, yB,i) であることをあらわす。(xB,1, yB,1) と(xB,2, yB,2) が、結ぶべき２つの街の座標である。

どの２つの街の座標も異なっており、どの３つの街も同一直線上にないと仮定してよい。

Output

問題文の条件をみたすように道を建設したとき、道の長さの合計の最小値を出力せよ。ここで言う
「長さ」とは、ユークリッド距離のことである。ただし、どうやっても条件をみたす道を建設できな
いときは、代わりに-1 を出力せよ。出力は誤差を含んでいてもよいが、真の値との相対誤差が10-9未満でなければならない。

Sample Input 1

2 2
0 0
1 1
2 0
2 -1

Sample Output 1

2.414213562373

Sample Input 2

2 3
4 0
0 0
2 3
2 -2
3 1

Sample Output 2

-1

Sample Input 3

5 2
-2 1
1 2
-1 3
-1 5
1 4
0 4
0 0

Sample Output 3

12.359173603117

Solution in Rust (judge verdict: Accepted)

use std::ops::Sub;
use std::collections::BinaryHeap;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer
}
fn read_lines<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split(' ').map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
fn read_tabulate<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
macro_rules! define {
    () => {};
    ($($token:tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        define_iter!(iter, $($token)*);
    };
}
macro_rules! define_iter {
    ($iter:expr) =>{};
    ($iter:expr,) =>{};
    ($iter:expr, $id:ident:$t:tt $($tail:tt)*) => {
        let $id: $t = $iter.next().unwrap().parse().ok().expect("Can't Parse");
        define_iter!($iter, $($tail)*);
    };
    ($iter:expr, mut $id:ident:$t:tt $($tail:tt)*) => {
        let mut $id: $t = $iter.next().unwrap().parse().ok().expect("Can't Parse");
        define_iter!($iter, $($tail)*)
    };
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
struct Point {
    x: i32, y: i32
}
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
struct Vector {
    dx: i32, dy: i32
}
impl Sub for Point {
    type Output = Vector;
    fn sub(self, rhs: Self) -> Self::Output {
        Vector{dx: self.x - rhs.x, dy: self.y - rhs.y}
    }
}
impl Point {
    fn distance(&self, rhs: &Point) -> f64 {
        self.sub(*rhs).length()
    }
}
impl Vector {
    fn length(&self) -> f64 {
        ((self.dx * self.dx + self.dy * self.dy) as f64).sqrt()
    }
    fn cross(&self, that: &Vector) -> i32 {
        self.dx * that.dy - self.dy * that.dx 
    }
    fn dot(&self, that: &Vector) -> i32 {
        self.dx * that.dx + self.dy * that.dy
    }
}
#[derive(Copy, Clone, Default, Debug)]
struct Line {
    end_a: Point, end_b: Point
}
impl Line {
    fn is_cross(&self, that: &Self) -> bool {
        self.separate_by_line(that.end_a, that.end_b) && 
            that.separate_by_line(self.end_a, self.end_b)
    }
    fn separate_by_line(&self, c: Point, d: Point) -> bool {
        let ab = self.end_a - self.end_b;
        let cb = c - self.end_b;
        let db = d - self.end_b;
        ab.cross(&cb).signum() * ab.cross(&db).signum() <= 0
    }
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
} 
#[derive(PartialEq, Eq, Debug, Copy, Clone, Default, Hash)]
struct Reverse<T>(T);
impl <T: PartialOrd> PartialOrd for Reverse<T> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        other.0.partial_cmp(&self.0)
    }
}
impl <T: Ord> Ord for Reverse<T> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        other.0.cmp(&self.0)
    }
}

fn min_length(points: &Vec<Point>, barrier: Line) -> Option<f64> {
    let max = 1e100;
    let mut min_len = vec![max; points.len()];
    let mut heap = BinaryHeap::new();
    min_len[0] = 0f64;
    heap.push(Reverse(KeyValue{key: 0f64, value: 0}));
    while let Some(Reverse(KeyValue{key: cost, value: current})) = heap.pop() {
        if min_len[current] > cost {continue;}
        for next in 0usize .. points.len() {
            if next != current {
                let line = Line{ end_a: points[current], end_b: points[next] };
                if line.is_cross(&barrier) {continue;}
                let len = points[current].distance(&points[next]);
                if min_len[next] > len + cost {
                    min_len[next] = len + cost;
                    heap.push(Reverse(KeyValue{key: len + cost, value: next}));
                }
            }
        }
    }
    if min_len[1] != max {
        Some(min_len[1] + barrier.end_a.distance(&barrier.end_b))
    }else {
        None
    }
}
fn main() {
    define! {
        na: usize
        nb: usize
    }
    let tutete = (0 .. na).map(|_| {
        define!{
            x: i32
            y: i32
        }
        Point{x, y}
    }).collect::<Vec<_>>();
    let totata = (0 .. nb).map(|_| {
        define!{
            x: i32
            y: i32
        }
        Point{x, y}
    }).collect::<Vec<_>>();
    let for_tutete = min_length(&tutete, Line{end_a: totata[0], end_b: totata[1]});
    let for_totata = min_length(&totata, Line{end_a: tutete[0], end_b: tutete[1]});
    if let Some(a) = for_tutete {
        if let Some(b) = for_totata {
            println!("{:.15}", if a < b { a } else { b });
        }else {
            println!("{:.15}", a);
        }
    }else if let Some(a) = for_totata {
        println!("{:.15}", a);
    }else {
        println!("-1");
    }
}