#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <numeric>
#include <queue>
#include <stack>
#include <map> 
#include <set>
#include <string>
#include <functional>
#include <list>
#include <random>
#include <time.h>
#include <iomanip>
#include <assert.h>
#include <numeric>
#include <new>
#define BIT(nr) (1ULL << (nr))
#define int long long
#define ll long long
#define double long double
#define mod 1000000007
#define MAXN (int)1e+5 * 2+1
#define LL_MAX 9223372036854775807	//ない環境用
#define LL_HALFMAX 9223372036854775807 / 2	//ない環境用
#define MIN -(9223372036854775807 / 2)
#define REP(i,a,n) for(int i=(a); i<(int)(n); i++)
#define rep(i,n) REP(i,0,n)
#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin(); it!=(c).end(); ++it)
#define ALLOF(c) (c).begin(), (c).end()
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define mp make_pair
template<typename T1, typename T2> inline void chmin(T1 & a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1& a, T2 b) { if (a < b) a = b; }


using namespace std;

using Weight = int;
using Flow = int;
struct Edge {
    int src, dst;
    Weight weight;
    Flow cap;
    Edge() : src(0), dst(0), weight(0) {}
    Edge(int s, int d, Weight w) : src(s), dst(d), weight(w) {}
};
using Edges = std::vector<Edge>;
using Graph = std::vector<Edges>;
using Array = std::vector<Weight>;
using Matrix = std::vector<Array>;

void add_edge(Graph &g, int a, int b, Weight w = 1) {
    g[a].emplace_back(a, b, w);
    g[b].emplace_back(b, a, w);
}
void add_arc(Graph &g, int a, int b, Weight w = 1) { g[a].emplace_back(a, b, w); }

template< typename T, typename E = T >
struct SkewHeap {
    using G = function< T(T, E) >;
    using H = function< E(E, E) >;

    struct Node {
        T key;
        E lazy;
        Node *l, *r;
    };

    const bool rev;
    const G g;
    const H h;

    SkewHeap(bool rev = false) : g([](const T &a, const E &b) { return a + b; }),
        h([](const E &a, const E &b) { return a + b; }), rev(rev) {}

    SkewHeap(const G &g, const H &h, bool rev = false) : g(g), h(h), rev(rev) {}

    Node *propagate(Node *t) {
        if (t->lazy != 0) {
            if (t->l) t->l->lazy = h(t->l->lazy, t->lazy);
            if (t->r) t->r->lazy = h(t->r->lazy, t->lazy);
            t->key = g(t->key, t->lazy);
            t->lazy = 0;
        }
        return t;
    }

    Node *merge(Node *x, Node *y) {
        if (!x || !y) return x ? x : y;
        propagate(x), propagate(y);
        if ((x->key > y->key) ^ rev) swap(x, y);
        x->r = merge(y, x->r);
        swap(x->l, x->r);
        return x;
    }

    void push(Node *&root, const T &key) {
        root = merge(root, new Node({ key, 0, nullptr, nullptr }));
    }

    T top(Node *root) {
        return propagate(root)->key;
    }

    T pop(Node *&root) {
        T top = propagate(root)->key;
        auto *temp = root;
        root = merge(root->l, root->r);
        delete temp;
        return top;
    }

    bool empty(Node *root) const {
        return !root;
    }

    void add(Node *root, const E &lazy) {
        if (root) {
            root->lazy = h(root->lazy, lazy);
            propagate(root);
        }
    }

    Node *makeheap() {
        return nullptr;
    }
};

struct uf_tree {
    std::vector<int> parent;
    int __size;
    uf_tree(int size_) : parent(size_, -1), __size(size_) {}
    void unite(int x, int y) {
        if ((x = find(x)) != (y = find(y))) {
            if (parent[y] < parent[x]) std::swap(x, y);
            parent[x] += parent[y];
            parent[y] = x;
            __size--;
        }
    }
    bool is_same(int x, int y) { return find(x) == find(y); }
    int find(int x) { return parent[x] < 0 ? x : parent[x] = find(parent[x]); }
    int size(int x) { return -parent[find(x)]; }
    int size() { return __size; }
};


signed main() {
    int N, M;
    cin >> N >> M;
    vector<int> a(N);
    rep(i, N) {
        cin >> a[i];
    }

    uf_tree uf(N);

    rep(i, M) {
        int x, y;
        cin >> x >> y;
        uf.unite(x, y);
    }

    SkewHeap<int> sq(false);
    
    map<int, SkewHeap<int>::Node*> heaps;
    
    int groups = 0;

    rep(i, N) {
        int parent = uf.find(i);
        if (heaps.find(parent) == heaps.end())
        {
            heaps[parent] = sq.makeheap();
            groups++;
        }
        sq.push(heaps[parent], a[i]);
    }

    bool first = true;

    SkewHeap<int>::Node* calc = sq.makeheap();

    int ans = 0;

    if (groups == 1) {
        cout << 0 << "\n";
        return 0;
    }

    for (auto p : heaps) {
        int t = sq.pop(p.second);
        ans += t;
        while (!sq.empty(p.second)) {
            sq.push(calc, sq.pop(p.second));
        }
    }

    rep(i, (groups - 1) * 2 - groups) {
        if (sq.empty(calc)) {
            cout << "Impossible\n";
            return 0;
        }

        int t = sq.pop(calc);
        ans += t;
    }

    /*
    これは嘘で、必ずしも最小同士を組み合わせるのが最適とは限らない
    for (auto p : heaps) {
        if (calc == nullptr && first) {
            calc = p.second;
            first = false;
            continue;
        }
        //途中でcalc が無くなったらNG
        if (sq.empty(calc)) {
            cout << "Impossible\n";
            return 0;
        }
        int a1 = sq.pop(calc);
        int a2 = sq.pop(p.second);
        ans += a1 + a2;
        calc = sq.merge(calc, p.second);
    }
    */

    cout << ans << "\n";

    return 0;
}


Measured memory_bytes: 12800