Problem:
Score : 600 points

Problem Statement

You are given a forest with N vertices and M edges. The vertices are numbered 0 through N-1.
The edges are given in the format (x_i,y_i), which means that Vertex x_i and y_i are connected by an edge.

Each vertex i has a value a_i.
You want to add edges in the given forest so that the forest becomes connected.
To add an edge, you choose two different vertices i and j, then span an edge between i and j.
This operation costs a_i + a_j dollars, and afterward neither Vertex i nor j can be selected again.

Find the minimum total cost required to make the forest connected, or print Impossible if it is impossible.

Constraints

1 ≤ N ≤ 100,000

0 ≤ M ≤ N-1

1 ≤ a_i ≤ 10^9

0 ≤ x_i,y_i ≤ N-1

The given graph is a forest.

All input values are integers.

Input

Input is given from Standard Input in the following format:

N M
a_0 a_1 .. a_{N-1}
x_1 y_1
x_2 y_2
:
x_M y_M

Output

Print the minimum total cost required to make the forest connected, or print Impossible if it is impossible.

Sample Input 1

7 5
1 2 3 4 5 6 7
3 0
4 0
1 2
1 3
5 6

Sample Output 1

7

If we connect vertices 0 and 5, the graph becomes connected, for the cost of 1 + 6 = 7 dollars.

Sample Input 2

5 0
3 1 4 1 5

Sample Output 2

Impossible

We can't make the graph connected.

Sample Input 3

1 0
5

Sample Output 3

0

The graph is already connected, so we do not need to add any edges.

Solution in Rust (1.15.1) (judge verdict: Wrong Answer)

#![allow(unused_imports, unused_macros, unknown_lints)]

use std::collections::*;
use std::cmp::Ordering::*;

macro_rules! dump {($($e:expr), +) => {print!(concat!($(stringify!($e), " = {:?}\n"), +), $($e), +)}}
macro_rules! max {($e0:expr, $($e:expr), +) => {{let mut r = $e0; $(r = std::cmp::max(r, $e);)+ r}}}
macro_rules! min {($e0:expr, $($e:expr), +) => {{let mut r = $e0; $(r = std::cmp::min(r, $e);)+ r}}}

fn main() {
  let (n,m) = get::tuple::<usize,usize>();
  let bs = get::vec::<isize>();
  let xys = get::tuples::<usize,usize>(m);
  
  let mut uf = UnionFind::new(n);
  for (x,y) in xys {uf.unite(x,y)}
  
  let mut mp = HashMap::new();
  for i in 0 .. n {
    let empty = vec![];
    let vs = mp.entry(uf.rep(i)).or_insert(empty);
    (*vs).push(-bs[i]);
  }
  
  let mut pq_some = BinaryHeap::new();
  let mut pq_one  = BinaryHeap::new();
  
  for v in mp.values_mut() {
    v.sort_by(|x,y|y.cmp(&x));
    let dq = v.into_iter().collect::<VecDeque<_>>();
    if dq.len() == 1 {pq_one.push(dq)} else {pq_some.push(dq)}
  }

  let mut ans = 0;
  for _ in 0 .. n-m-1 {
    let t1 = pq_some.pop();
    if t1.is_none() {
      println!("Impossible");
      return
    }
    
    let mut t1 = t1.unwrap();
    let b1 = t1.pop_front().unwrap();
    
    match (pq_some.pop(), pq_one.pop()) {
      (Some(mut ts), None) => {
        let b2 = ts.pop_front().unwrap();
        ans += (-*b1) + (-*b2);    
        if ts.len() == 1 {pq_one.push(ts)} else if t1.len() != 0 {pq_some.push(ts)}},          
      (Some(mut ts), Some(mut to)) => {
        if *ts[0] >= *to[0] {
          let b2 = ts.pop_front().unwrap();
          ans += (-*b1) + (-*b2);    
          if ts.len() == 1 {pq_one.push(ts)} else if ts.len() != 0 {pq_some.push(ts)};
          pq_one.push(to)
        } else {
          let b2 = to.pop_front().unwrap();
          ans += (-*b1) + (-*b2);
          pq_some.push(ts)
        }},
      (None, Some(mut to)) => {
        let b2 = to.pop_front().unwrap();
        ans += (-*b1) + (-*b2)},
      _ => unreachable!()
    }
    if t1.len() == 1 {pq_one.push(t1)} else if t1.len() != 0 {pq_some.push(t1)}
  }
  
  println!("{}", ans)
}

#[allow(dead_code)]
struct UnionFind {
  size: usize,
  rp: Vec<usize>,
  rk: Vec<usize>
}

#[allow(dead_code)]
impl UnionFind {
  fn new(n: usize) -> UnionFind {
    UnionFind {
      size: n,
      rp: (0..n).collect(),
      rk: vec![1; n]
    }
  }

  fn rep(&self, p: usize) -> usize {
    if self.rp[p] == p {p} else {self.rep(self.rp[p])}
  }

  fn rank(&self, p: usize) -> usize {
    self.rk[self.rep(p)]
  }

  fn same(&self, p: usize, q: usize) -> bool {
    self.rep(p) == self.rep(q)
  }

  fn count(&self) -> usize {
    let mut reps = (0..self.size).map(|x|self.rep(x)).collect::<Vec<_>>();
    reps.sort();
    reps.dedup();
    reps.len()
  }

  fn unite(&mut self, p: usize, q:usize) {
    let repp = self.rep(p);
    let repq = self.rep(q);
    if repp == repq {return}

    let rkp = self.rk[repp];
    let rkq = self.rk[repq];
    let (p, repp, repq) = if rkp <= rkq {(p, repp, repq)} else {(q, repq, repp)};

    self.rp[p] = repq;
    self.rp[repp] = repq;
    self.rk[repq] += self.rk[repp];
  }
}

#[allow(dead_code)]
mod get {
  use std::io::*;
  use std::str::*;
  use std::process::*;

  pub fn val<T: FromStr>() -> T {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    buf.trim_right().parse::<T>().ok().unwrap()
  }

  pub fn vals<T: FromStr>(n: usize) -> Vec<T> {
    let mut vec: Vec<T> = vec![];
    for _ in 0 .. n {
      vec.push(val());
    }
    vec
  }

  pub fn tuple<T1: FromStr, T2: FromStr>() -> (T1, T2) {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    let mut it = buf.trim_right().split_whitespace();
    let x = it.next().unwrap().parse::<T1>().ok().unwrap();
    let y = it.next().unwrap().parse::<T2>().ok().unwrap();
    (x, y)
  }

  pub fn tuples<T1: FromStr, T2: FromStr>(n: usize) -> Vec<(T1, T2)> {
    let mut vec: Vec<(T1, T2)> = vec![];
    for _ in 0 .. n {
      vec.push(tuple());
    }
    vec
  }

  pub fn tuple3<T1: FromStr, T2: FromStr, T3: FromStr>() -> (T1, T2, T3) {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    let mut it = buf.trim_right().split_whitespace();
    let x = it.next().unwrap().parse::<T1>().ok().unwrap();
    let y = it.next().unwrap().parse::<T2>().ok().unwrap();
    let z = it.next().unwrap().parse::<T3>().ok().unwrap();
    (x, y, z)
  }

  pub fn tuple3s<T1: FromStr, T2: FromStr, T3: FromStr>(n: usize) -> Vec<(T1, T2, T3)> {
    let mut vec: Vec<(T1, T2, T3)> = vec![];
    for _ in 0 .. n {
      vec.push(tuple3());
    }
    vec
  }

  pub fn vec<T: FromStr>() -> Vec<T> {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    buf.trim_right().split_whitespace().map(|t| t.parse::<T>().ok().unwrap()).collect()
  }

  pub fn mat<T: FromStr>(h: usize) -> Vec<Vec<T>> {
    let mut mat = vec![];
    for _ in 0 .. h {
      mat.push(vec());
    }
    mat
  }

  pub fn chars() -> Vec<char> {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    buf.trim_right().chars().collect()
  }
}

#[allow(dead_code)]
mod put {
  use std::string::*;

  pub fn vec<T: ToString>(vec: &Vec<T>, sep: &str) {
    let out = vec.iter().map(|e| e.to_string()).collect::<Vec<_>>().as_slice().join(sep);
    println!("{}", out);
  }

  pub fn mat<T: ToString>(mat: &Vec<Vec<T>>, sep: &str) {
    for v in mat {
      vec(v, sep);
    }
  }
}