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 Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.io.*;
import java.util.*;

public class Main {
    
    class DisjointSets {
        int[] parent;
        int[] rank;

        public DisjointSets(int size) {
            parent = new int[size];
            for (int i = 0; i < size; i++) parent[i] = i;
            rank = new int[size];
        }

        public int find(int n) {
            while ( n != parent[n] ) {
                parent[n] = parent[ parent[n] ];
                n = parent[n];
            }
            return n;
        }

        public void union(int u, int v) {
            u = find(u);
            v = find(v);
            
            if (u == v) return;
            
            if (rank[u] < rank[v]) {
                parent[u] = v;
            } else {
                parent[v] = u;
                if (rank[u] == rank[v]) rank[u]++;
            }
        }
    }
    
    class Answer {
        int N, M;
        int[] arr;
        
        public long solve(DisjointSets ds) {            
            if (N < 2*(N-M-1)) return -1;
            
            ArrayList<Integer>[] costs = new ArrayList[N];
            
            for (int i = 0; i < N; i++) {
                int pi = ds.find(i);
                if ( costs[pi] == null ) costs[pi] = new ArrayList<>();
                costs[pi].add( arr[i] );
            }
            
            ArrayList<Integer> leftover = new ArrayList<>();
            long sum = 0L;
            for (int i = 0; i < N; i++) {
                if (costs[i] != null) {
                    Collections.sort(costs[i]);
                    sum += costs[i].get(0);
                    pl(costs[i].get(0));
                    leftover.addAll( costs[i].subList(1, costs[i].size()) );
                }
            }
            if (leftover.size() < N-M-2) return -1;
            
            Collections.sort(leftover);
            
            for (int i = N-M; i < 2*(N-M-1); i++) {
                sum += leftover.get( i-(N-M) );
            }
            
            return sum;
        }
        
        public void print(ArrayList<Integer>[] costs) {
            int k = 0;
            for (ArrayList<Integer> c : costs) {
                p(k + " ");
                pl(c);
                k++;
            }    
        }
        
        public void main(FastScanner in, PrintWriter out) {
            N = in.nextInt();
            M = in.nextInt();
            arr = new int[N];
            for (int i = 0; i < N; i++) arr[i] = in.nextInt();
                
            DisjointSets ds = new DisjointSets(N);
                
            for (int i = 0; i < M; i++) {
                int u = in.nextInt();
                int v = in.nextInt();
                ds.union(u, v);
            }
            
            long ret = solve(ds);
            out.println( ret == -1 ? "Impossible" : ret );
        }
        
        public void p(Object o) { System.out.print(o); }
        public void pl(Object o) { System.out.println(o); }
        public void arp(int[] o) { pl( Arrays.toString(o) ); }
        public void arpp(int[][] o) { 
            for (int i = 0; i < o.length; i++) {
                for (int j = 0; j < o[0].length; j++) { p(o[i][j] + " "); }
                pl("");
            }
        }
        public void ck(Object o1, Object o2) { pl(o1 + " " + o2); }
        public void ckk(Object o1, Object o2, Object o3) { pl(o1 + " " + o2 + " " + o3); }
        public void ckkk(Object o1, Object o2, Object o3, Object o4) { 
            pl(o1 + " " + o2 + " " + o3 + " " + o4);
        }
    }

    public static void main(String[] args) throws Exception {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        
        Main problem = new Main();
        Answer ans = problem.new Answer();
        ans.main(in, out);
        
        out.close();
        in.close();
    }
    
    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;
        public FastScanner(InputStream in) { br = new BufferedReader(new InputStreamReader(in)); }
        public int nextInt() { return Integer.parseInt(next()); }
        public long nextLong() { return Long.parseLong(next()); }
        public double nextDouble() { return Double.parseDouble(next()); }
        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try { st = new StringTokenizer(br.readLine()); } 
                catch (IOException e) { e.printStackTrace(); }
            }
            return st.nextToken();
        }
        public String nextLine() {
            String str = "";
            try { str = br.readLine();
            } catch (IOException e) { e.printStackTrace(); }
            return str;
        }
        public void close() throws IOException { br.close(); }
    }
}