Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Modern Announce Network

Today, modern teenagers use SNS to communicate with each other.

In a high school, $N$ students are using an SNS called ICPC (International Community for Programming Contest). Some pairs of these $N$ students are 'friends' on this SNS, and can send messages to each other. Among these $N$ students, $A$ first grade students, $B$ second grade students, and $C$ third grade students are members of the Programming Society. Note that there may be some students who are not the members of the Programming Society, so $A+B +C$ can be less than $N$.

There are good relationships between members of the same grade in the Society. Thus, there is a chat group in the SNS for each grade, and the Society members of the same grade can communicate with each other instantly via their group chat. On the other hand, the relationships between any different grades are not so good, and there are no chat group for the entire Society and the entire high school.

In order to broadcast a message to all the Society members on the SNS, the administrator of the Society came up with a method: the administrator tells the message to one of the $N$ students and have them spread the message on the SNS via the chat groups and their friends. (The administrator itself does not have an account for the SNS.) As the members of the same grade can broadcast the message by the chat group for the grade, we can assume that if one of a grade gets the message, all other members of that grade also get the message instantly. Therefore, if the message is told to at least one member of each grade, we can assume that the message is broadcasted to the all members of the Society on the SNS.

Because it is bothering to communicate between friends, we want to minimize the number of communications between friends. What is the minimum number of communications between friends to broadcast a message to all the Society members? Who is the first person to whom the administrator should tell the message to achieve the minimum communications?

Input

The input consists of a single test case. The test case is formatted as follows:

$N$ $A$ $B$ $C$

$a_1$ ... $a_A$

$b_1$ ... $b_B$

$c_1$ ... $c_C$

$M$

$x_1$ $y_1$

...

$x_M$ $y_M$

The first line contains four integers $N$, $A$, $B$, and $C$. $N$ ($3 \leq N \leq 10,000$) denotes the number of students in the SNS, and $A$, $B$ and $C$ ($1 \leq A,B,C \leq N$ and $A + B + C \leq N$) denote the number of members of the first, second, and third grade respectively. Each student on the SNS is represented by a unique numeric ID between 1 and $N$. The second line contains $A$ integers $a_1, ..., a_A$ ($1 \leq a_1, ..., a_A \leq N$), which are the IDs of members of the first grade. The third line contains $B$ integers $b_1, ..., b_B$ ($1 \leq b_1, ..., b_B \leq N$), which are the IDs of members of the second grade. The fourth line contains $C$ integers $c_1, ..., c_C$ ($1 \leq c_1, ... , c_C \leq N$), which are the IDs of members of the third grade. You can assume that $a_1, ..., a_A, b_1, ... , b_B, c_1, ..., c_C$ are distinct. The fifth line contains an integer $M$ ($2 \leq M \leq 500,000$). $M$ denotes the number of pairs of students who are friends in the SNS. The $i$-th line of the following $M$ lines contains two integers $x_i$ and $y_i$ ($1 \leq x_i, y_i \leq N$), which means the student with ID $x_i$ and the student with ID $y_i$ are friends in the SNS. You can assume that $x_i \ne y_i$ ($1 \leq i \leq M$), and ($x_i \ne x_j$ or $y_i \ne y_j$) and ($x_i \ne y_j$ or $y_i \ne x_j$) if $i \ne j$ ($1 \leq i, j \leq M$). You can also assume that a message can be delivered from any student to any student in the SNS via the friends and group chat.

Output

Output the minimum number of communications between friends (not including group chat) to broadcast a message among all the Society members, and the ID of the student to whom the administrator should tell the message in order to achieve the minimum number of communications, separated by a single space. If there are multiple students that satisfy the above constraints, output the minimum ID of such students.

Sample Input 1

4 2 1 1
1 2
3
4
3
1 2
2 4
3 4

Output for the Sample Input 1

2 1

Sample Input 2

4 1 1 1
2
3
4
4
1 2
1 3
1 4
2 4

Output for the Sample Input 2

3 1

Sample Input 3

8 1 2 2
5
4 6
3 8
7
1 2
2 3
3 4
5 6
6 7
7 8
2 6

Output for the Sample Input 3

2 3

Solution in Rust (judge verdict: Accepted)

use std::collections::HashSet;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::{AddAssign, Sub};
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::BTreeSet;
use std::cmp::Ordering;
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<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
}
fn read_tabulate<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>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read_lines {
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
}
macro_rules! read {
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    (mut $ident: ident: [[$ty:ty]; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    ($ident: ident: [[$ty:ty]; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$ty:ty; $size:expr]) => {
        let mut $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
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()
    }
}
fn cal_depth(nodes: &Vec<Vec<usize>>, source: usize) -> Vec<i32> {
    let mut queue = VecDeque::new();
    queue.push_front(source);
    let mut result = vec![-1; nodes.len()];
    result[source] = 0;
    while let Some(top) = queue.pop_front() {
        for &next in &nodes[top] {
            if result[next] == -1 {
                result[next] = result[top] + 1;
                queue.push_back(next);
            }
        }
    }
    result
}
struct UnionFind {
    vec: Vec<i32>
}
impl UnionFind {
    fn new(size: usize) -> UnionFind {
        UnionFind{vec: vec![-1; size]}
    }
    fn find(&mut self, a: usize) -> usize {
        if self.vec[a] < 0 {
            a
        }else {
            let parent = self.vec[a] as usize;
            let root = self.find(parent);
            self.vec[a] = root as i32;
            root
        }
    }
    fn same(&mut self, a: usize, b: usize) -> bool {
        self.find(a) == self.find(b)
    }
    fn unite(&mut self, mut a: usize, mut b: usize) {
        a = self.find(a);
        b = self.find(b);
        if self.vec[a] < self.vec[b] {
            self.vec[a] += self.vec[b];
            self.vec[b] = a as i32;
        }else {
            self.vec[b] += self.vec[a];
            self.vec[a] = b as i32;
        }
    }
}
fn main() {
    read!{
        n: usize, a: usize, b: usize, c: usize
    }
    read!{
        a_students: [usize]
    }
    read! {
        b_students: [usize]
    }
    read! {
        c_students: [usize]
    }
    assert_eq!(a, a_students.len());
    assert_eq!(b, b_students.len());
    assert_eq!(c, c_students.len());
    let mut degree = vec![0usize; n + 4];
    for i in 1 .. 4 {
        degree[n + i] = i;
    }
    for &ai in &a_students {
        degree[ai] = 1;
    }
    for &bi in &b_students {
        degree[bi] = 2;
    }
    for &ci in &c_students {
        degree[ci] = 3;
    }
    read!{
        m: usize
    }
    read_lines! {
        links: [{
            read!(x: usize, y: usize);
            (x, y)
        }; m]
    }
    let mut nodes = vec![Vec::<usize>::new(); n + 4];
    for &(x, y) in &links {
        let x = if degree[x] != 0 {
            n + degree[x]
        }else {
            x
        };
        let y = if degree[y] != 0 {
            n + degree[y]
        }else {
            y
        };
        nodes[x].push(y);
        nodes[y].push(x);
    }
    let mut depth_from = vec![Vec::new(); 4];
    for i in 1 .. 4 {
        let depth = cal_depth(&nodes, n + i);
        depth_from[i] = depth;
    }
    let min_cost = (0 .. n + 4).map(|mut x| {
        x = if degree[x] != 0 {n + degree[x]} else {x};
        if (1 .. 4).any(|i| depth_from[i][x] < 0) {
            std::i32::MAX
        }else {
            (1 .. 4).map(|i| depth_from[i][x]).sum()
        }
    }).collect::<Vec<_>>();
    let &result = min_cost.iter().min().unwrap();
    let mut on_min_path_to = vec![vec![false; n + 4]; 4];
    for i in 1 .. n + 4 {
        if min_cost[i] != result { continue; }
        for to in 1 .. 4 {
            if on_min_path_to[to][i] {continue;}
            on_min_path_to[to][i] = true;
            let mut queue = VecDeque::new(); queue.push_back(i);
            while let Some(top) = queue.pop_front() {
                for &next in &nodes[top] {
                    if on_min_path_to[to][next] {continue;}
                    if depth_from[to][next] + 1 != depth_from[to][top] {continue;}
                    on_min_path_to[to][next] = true;
                    queue.push_back(next);
                }
            }
        }
    }
    let first = (1 .. n + 1).find(|&i| {
        degree[i] != 0 || (1 .. 4).any(|to| on_min_path_to[to][i])
    }).unwrap();
    println!("{} {}", result, first);
}