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: Time Limit Exceeded)

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.util.Comparator;
import java.io.InputStream;
 
/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author rizhiy
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }
 
    static class TaskD {
        int[] st;
        ArrayList<Integer>[] g;
        ArrayList<Integer> p;
        boolean[] used;
        long answ = 0;
 
        void dfs(int v) {
            p.add(st[v]);
            used[v] = true;
            for (int to : g[v]) {
                if (!used[to]) {
                    dfs(to);
                }
            }
        }
 
        int[] marg(int[] a, int[] b) {
            answ += (long) a[0] + (long) b[0];
            ArrayList<Integer> p = new ArrayList<>();
            int i = 1;
            int j = 1;
            while (true) {
                if (i < a.length && j < b.length) {
                    if (a[i] < b[j]) {
                        p.add(a[i]);
                        i++;
                    } else {
                        p.add(b[j]);
                        j++;
                    }
                } else if (i < a.length && j >= b.length) {
                    p.add(a[i]);
                    i++;
                } else if (i >= a.length && j < b.length) {
                    p.add(b[j]);
                    j++;
                } else {
                    break;
                }
            }
            int[] k = new int[p.size()];
            for (int ii = 0; ii < p.size(); ii++) {
                k[ii] = p.get(ii);
            }
            return k;
        }
 
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            st = new int[n];
            for (int i = 0; i < n; i++) {
                st[i] = in.nextInt();
            }
            g = new ArrayList[n];
            used = new boolean[n];
            for (int j = 0; j < n; j++) {
                g[j] = new ArrayList<>();
            }
            for (int i = 0; i < m; i++) {
                int x = in.nextInt();
                int y = in.nextInt();
                g[x].add(y);
                g[y].add(x);
            }
            PriorityQueue<int[]> treeSet = new PriorityQueue<>(new Comparator<int[]>() {
 
                public int compare(int[] o1, int[] o2) {
//                if (o1.length != o2.length)
                    return o2.length - o1.length;
//                for (int i = 0; i < o1.length; i++)
//                    if (o1[i] != o2[i])
//                        return o1[i] - o2[i];
//                return 0;
                }
            });
            for (int i = 0; i < n; i++) {
                if (!used[i]) {
                    p = new ArrayList<>();
                    dfs(i);
                    int[] k = new int[p.size()];
                    for (int j = 0; j < p.size(); j++) {
                        k[j] = p.get(j);
                    }
                    Arrays.sort(k);
                    treeSet.add(k);
                }
            }
            while (true) {
                if (treeSet.size() == 1) break;
                int[] a = treeSet.poll();
                int[] b = treeSet.poll();
                if (a.length < 1 || b.length < 1) {
                    out.println("Impossible");
                    return;
                }
                int[] o = marg(a, b);
                if (o.length < 1) {
                    out.println("Impossible");
                    return;
                }
                treeSet.add(o);
            }
            out.println(answ);
        }
 
    }
 
    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
 
        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }
 
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
 
        public int nextInt() {
            return Integer.parseInt(next());
        }
 
    }
}