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: Accepted)

#![allow(non_snake_case,unused_imports,dead_code)]
use std::io::Read;
use std::cmp::max;
use std::cmp::min;
use std::str::FromStr;
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::BinaryHeap;

fn main() {
    let mut buf = String::new();
    std::io::stdin().read_to_string(&mut buf).unwrap();
    let mut buf_it = buf.split_whitespace();

    let N = buf_it.next().unwrap().parse::<usize>().unwrap();
    let M = buf_it.next().unwrap().parse::<usize>().unwrap();
    let A = (0..N).map(|_| buf_it.next().unwrap().parse::<usize>().unwrap()).collect::<Vec<_>>();
    let XY = (0..M).map(|_| 
        (buf_it.next().unwrap().parse::<usize>().unwrap(),
         buf_it.next().unwrap().parse::<usize>().unwrap())
    ).collect::<Vec<_>>();

    let mut U = UnionFind::new(N);
    for &(x,y) in &XY{
        U.merge(x,y);
    }
    let mut C = (0..N).map(|_| Vec::new()).collect::<Vec<_>>();
    for i in 0..N{
        let p = U.get_parent(i);
        C[p].push(A[i]);
    }
    let mut t = 0;
    let mut ans = 0;
    for i in 0..N{
        if C[i].len()==0{continue;}
        t += 1;
        C[i].sort_by_key(|&x| 1_000_000_100-x);
        ans += C[i].pop().unwrap();
    }
    if t==1{ ans = 0;}
    if (t-1)*2 > N{
        println!("Impossible");
        return;
    }
    let mut D = Vec::new();
    for i in 0..N{
        D.append(&mut C[i]);
    }
    D.sort();
    ans += (0..max(2,t)-2).map(|i| D[i]).sum::<usize>();

    println!("{}",ans);

}

struct UnionFind{
    P: Vec<usize>,
}

impl UnionFind {
    fn new(n:usize) -> UnionFind{
        UnionFind {P:(0..n).collect()}
    }
    fn get_parent(&mut self,n:usize) -> usize{
        if self.P[n] == n{ return n;}
        let p = self.P[n];
        self.P[n] = self.get_parent(p);
        self.P[n]
    }
    fn is_unite(&mut self,x:usize,y:usize) -> bool{
        self.get_parent(x)==self.get_parent(y)
    }
    fn merge(&mut self,x:usize,y:usize){
        if self.is_unite(x,y) {return;}
        let i = self.get_parent(x);
        let j = self.get_parent(y);
        self.P[j] = i;
    }
}