#include <bits/stdc++.h>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <iostream>
#include <bitset>
#include <cassert>
#include <queue>
#include <random>
#include <stack>
#include <iomanip>
#include <math.h>
using namespace std;
#define rep(i, n) for (ll i = 0; i < (ll)n; i++)
#define repf(i, a, b) for (ll i = (ll)a; i < (ll)b; i++)
#define repr(i, a, b) for (ll i = (ll)a; i > (ll)b; i--)
#define repv(x, arr) for (auto &x : arr)
#define all(v) (v).begin(), (v).end()
#define vec(name, num) vector<ll> name((num), 0);
#define mp(a, b) make_pair(a, b)
#define F first
#define S second
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<int> vii;
typedef vector<vii> vvii;
const ll mod = 1e9 + 7;
const int infi = 2147483600;
const ll infl = 1e17;

struct UnionFind
{
    vector<int> root;
    int n;
    void __init__(int sz)
    {
        n = sz;
        root.resize(n, -1);
    }
    int find(int x)
    {
        if (root[x] >= 0)
        {
            root[x] = find(root[x]);
            return root[x];
        }
        return x;
    }
    void unit(int a, int b)
    {
        int ra, rb;
        ra = find(a);
        rb = find(b);
        if (ra == rb)
        {
            return;
        }
        else if (root[ra] <= root[rb])
        {
            root[ra] += root[rb];
            root[rb] = ra;
        }
        else
        {
            root[rb] += root[ra];
            root[ra] = rb;
        }
        return;
    }
    int count()
    {
        set<int> cnt;
        rep(i, n)
            cnt.insert(find(i));
        return cnt.size();
    }
    bool check(){
        int cnt = 0;
        rep(i,n){
            if (root[i]==-1)
                cnt++;
        }
        return (cnt > 1);
    }
};
int n,m;


int main()
{
    cin >> n >> m;
    UnionFind UF;
    UF.__init__(n);
    vector<pii> a(n);
    rep(i,n){
        int ai;
        cin >> ai;
        a[i] = mp(ai, i);
    }
    rep(i,m){
        int x, y;
        cin >> x >> y;
        UF.unit(x, y);
    }
    if (2 * m + 2 < n)
    {
        cout << "Impossible" << endl;
        return 0;
    }
    ll ans = 0;
    vector<vector<pii>> data(n);
    rep(i,n){
        data[UF.find(i)].push_back(a[i]);
    }
    vector<bool> used(n, true);
    int need = 2 * (n - 1 - m);
    rep(i,n)
    {
        if (need == 0)
            break;
        if (!(data[i].empty())){
            //cout << ans << endl;
            sort(all(data[i]));
            ans += (*data[i].begin()).F;
            used[(*data[i].begin()).S] = false;
            need--;
        }
    }
    sort(all(a));
    rep(i,n){
        if (need==0)
            break;
        if (used[a[i].S]){
            ans += a[i].F;
            need--;
        }
    }
    cout << ans << endl;
    return 0;
    //各連結集合でもっともコストが小さい頂点を出しておく
    //上で選んだ頂点以外を全部まとめてみて
    //コストが小さい順に2(n-1-m)-(連結集合の個数)個を選ぶ
    

    //木を全て連結させたい。必要な辺の本数はN-1本、M本は既に実装されている


    //ここでN本目以降の辺は必要ないことが言える
    //なぜならN本以上になるとき、どこかで連結集合内での接続を行っていて、
    //辺のコストは正整数のため、削ることでコストを減らせる
    //このことから辺は高々N-1本である

    //したがってN-1-M本をどこかに引く必要がある
    //同じ点を2回以上端点として使用することはできない
    //なので2(N-1-M)個の頂点を選び、コストを最小化する

    //適当に選んで良いなら、小さい順に取ればよい
    //適当に選んで、全て連結にならない場合を考えて排除する
    //ある木の頂点を1つも選ばないとダメになる
    
    //また、各木で1つ以上選び、全体で2(N-1-M)個選べば例外を除き連結になる

    //Impossibleになる条件を考える
    //2(n-1-m)個選べないときである
    //頂点はN個しかないためN<2(N-1-M)となるとき、Impossible
    //M+1<Nはありえそう
}

Measured memory_bytes: 5760