// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5+100;

typedef long long LL;

int val[maxn],First[maxn],cnt,N,M;

int tot,pre[maxn];

LL ans = 0;

struct node{

    int to,Next;

}Tree[maxn*2];

void init(){

    memset(First,-1,sizeof(First));

    cnt = 0;

}

void addedge(int from,int to){

    Tree[cnt].to = to;

    Tree[cnt].Next = First[from];

    First[from] = cnt++;

}

priority_queue<int,vector<int>,greater<int> > Q[maxn];

void dfs(int u,int fa){

    pre[u] = 1;

    Q[tot].push(val[u]);

    for(int i = First[u];i!=-1;i=Tree[i].Next){

        int to = Tree[i].to;

        if(to==fa)continue;

        dfs(to,u);

    }

}

vector<int> ac,bc;

int main(){

    init();

    scanf("%d%d",&N,&M);

    for(int i = 0;i<=N-1;i++)scanf("%d",&val[i]);

    for(int i = 0;i<M;i++){

        int a,b;

        scanf("%d%d",&a,&b);

        addedge(a,b);

        addedge(b,a);

    }

    for(int i = 0;i<=N-1;i++){

        if(!pre[i]){

            tot++;

            dfs(i,-1);

            ac.push_back(tot);

        }

    }

    if(tot==1){

        printf("%d\n",0);

        return 0;

    }

    bool flag = 0;

    priority_queue<int,vector<int>,greater<int> >QQ;

    for(int i = 1;i<=tot;i++){

       ans+=Q[i].top();

       Q[i].pop();

       while(!Q[i].empty()){

        QQ.push(Q[i].top());

        Q[i].pop();

       }

    }

    int my =tot-2;

    if(QQ.size()<my){

        printf("Impossible\n");

        return 0;

    }

    for(int i = 0;i<my;i++){

        ans+=QQ.top();

        QQ.pop();

    }

    printf("%lld\n",ans);

    return 0;

}

/*

7 4

1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000

0 1

1 2

3 4

5 6

6 3

1 1 1 3 7 8

0 4

1 5

2 3

*/


// Faster C++ solution for the same problem (measured speedup: 4.825057836427249x):
#include <bits/stdc++.h>



using namespace std;



class dsu {

  public:

  vector<int> p;

  int n;



  dsu(int _n) : n(_n) {

    p.resize(n);

    iota(p.begin(), p.end(), 0);

  }



  inline int get(int x) {

    return (x == p[x] ? x : (p[x] = get(p[x])));

  }



  inline bool unite(int x, int y) {

    x = get(x);

    y = get(y);

    if (x != y) {

      p[x] = y;

      return true;

    }

    return false;

  }

};



int main() {

  int n, m;

  scanf("%d %d", &n, &m);

  vector<int> a(n);

  for (int i = 0; i < n; i++) {

    scanf("%d", &a[i]);

  }

  dsu d(n);

  for (int i = 0; i < m; i++) {

    int x, y;

    scanf("%d %d", &x, &y);

    d.unite(x, y);

  }

  vector< vector<int> > comp(n);

  for (int i = 0; i < n; i++) {

    comp[d.get(i)].push_back(a[i]);

  }

  int cnt = 0;

  for (int i = 0; i < n; i++) {

    if (!comp[i].empty()) {

      cnt++;

    }

  }

  if (cnt == 1) {

    puts("0");

    return 0;

  }

  int choose = 2 * cnt - 2;

  long long ans = 0;

  vector<int> other;

  for (int i = 0; i < n; i++) {

    if (!comp[i].empty()) {

      sort(comp[i].begin(), comp[i].end());

      ans += comp[i][0];

      choose--;

      for (int j = 1; j < (int) comp[i].size(); j++) {

        other.push_back(comp[i][j]);

      }

    }

  }

  if (choose > (int) other.size()) {

    puts("Impossible");

    return 0;

  }

  sort(other.begin(), other.end());

  for (int i = 0; i < choose; i++) {

    ans += other[i];

  }

  cout << ans << endl;

  return 0;

}