stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include<cmath>

#include<cstdio>

#include<algorithm>

#include<queue>

using namespace std;

typedef long long LL;

int n,m;

LL a[100000+10];

int par[100000+10];

priority_queue<LL> mini[100000+10];



int fpar(int x){

	if (par[x]==-1)return x;

	par[x]=fpar(par[x]);

	return par[x];

}

priority_queue <LL > pq1;

LL ans=0;

int main(){

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

	for (int f1=0;f1<n;f1++)scanf("%lld",&a[f1]);

	for (int f1=0;f1<n;f1++){par[f1]=-1;}

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

		int i,j;

		scanf("%d%d",&i,&j);

		i=fpar(i);

		j=fpar(j);

		par[j]=i;

	}

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

		int j=fpar(f1);

		mini[j].push(-a[f1]);

	}

	if (n==1+m){

		printf("0\n");

		return 0;

	}

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

		if (par[f1]==-1){

			ans-=mini[f1].top();

			mini[f1].pop();

			while (!mini[f1].empty()){

				pq1.push(mini[f1].top());

				mini[f1].pop();

			}	

		}

	}

	

	if (int(pq1.size())>=n-m-2){

		for (int f1=1;f1<=n-m-2;f1++){

			ans-=pq1.top();

			pq1.pop();

		}

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

	} else printf("Impossible\n");

}


// Faster C++ solution for the same problem (measured speedup: 4.260131687192634x):
#include <iostream>

#include<cstdio>

#include<set>

#include<queue>

#include<vector>

#include<map>

#include<cmath>

#include<cstdlib>

#include<algorithm>

#include<string>

#include<cstring>



using namespace std;



int a[100005],fa[100005],vis[100005],mi[100005];

priority_queue<pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > >q;



int _find(int x)

{

    return fa[x]==x?x:fa[x]=_find(fa[x]);

}



void _merge(int x,int y)

{

    int fx=_find(x),fy=_find(y);

    if(fx!=fy)

    {

        fa[fx]=fy;

    }

}

int main()

{

	int n,m;

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

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

	{

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

	    fa[i]=i;

	    mi[i]=1e9+9;

	}

	int x,y;

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

    {

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

        _merge(x,y);

    }

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

        _find(i);

    pair<int,int>tt;

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

	{

	    mi[fa[i]]=min(a[i],mi[fa[i]]);



	    tt.first=a[i];

	    tt.second=fa[i];

	    q.push(tt);

	}

	sort(fa,fa+n);

	int cnt=unique(fa,fa+n)-fa;

	if(cnt==1)

        printf("0\n");

    else

    {

        long long ans=0;

        for(int i=0;i<cnt;i++)

            ans+=mi[fa[i]];

        while(!q.empty())

        {

            if(cnt==2)

                break;

            pair<int,int>tmp;

            tmp=q.top();

            q.pop();

            if(vis[tmp.second]==0)

            {

                vis[tmp.second]=1;

                continue;

            }

            ans+=tmp.first;

            cnt--;

        }

        if(cnt==2)

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

        else

            printf("Impossible\n");

    }

    return 0;

}
// Slower C++ solution:
#include<cstdio>

#include<cstring>

#include<algorithm>

#include<cmath>

#include<vector>

#define SF scanf

#define PF printf

#define MAXN 100010

using namespace std;

int n,m,sum;

vector<int> a[MAXN];

bool vis[MAXN],used[MAXN];

int val[MAXN],b[MAXN];

long long ans;

int dfs(int x){

    vis[x]=1;

    int idx=x;

    for(int i=0;i<a[x].size();i++)

        if(vis[a[x][i]]==0){

            int id=dfs(a[x][i]);

            if(val[id]<val[idx])

                idx=id;

        }

    return idx;

}

int main(){

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

    int u,v;

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

        SF("%d",&val[i]);

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

        SF("%d%d",&u,&v);

        a[u].push_back(v);

        a[v].push_back(u);

    }

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

        if(vis[i]==0){

            int maxid=dfs(i);

            used[maxid]=1;

            sum++;

        }

    int cnt=2*sum-2,tot=0;

    if(sum==1){

        PF("0");

        return 0;

    }

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

        if(used[i]==1)

            ans+=val[i];

    cnt-=sum;

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

        if(used[i]==0)

            b[++tot]=val[i];

    if(cnt>tot){

        PF("Impossible");

        return 0;

    }

    sort(b+1,b+1+tot);

    for(int i=1;i<=cnt;i++)

        ans+=b[i];

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

}


// Faster C++ solution for the same problem (measured speedup: 3.446152730178429x):
#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;

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

using namespace std;

int n, m;

int a[100005];

struct Union_Find_Set {

	int fa[100005];

	void Init() {

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

			fa[i] = i;

		}

	}

	int Find(int x) {

		if (fa[x] != x) fa[x] = Find(fa[x]);

		return fa[x];

	}

	void Union(int x, int y) {

		fa[Find(x)] = Find(y);

	}

}ufs;

vector<int>vec[100005], v;

int main() {

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

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

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

	}

	int rem = (n - 1 - m) * 2;

	if (n < rem) {

		printf("Impossible\n");

		return 0;

	}

	if (rem == 0) {

		printf("0\n");

		return 0;

	}

	ufs.Init();

	for (int x, y, i = 1; i <= m; i++) {

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

		x++;

		y++;

		ufs.Union(x, y);

	}

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

		vec[ufs.Find(i)].push_back(a[i]);

	}

	long long ans = 0;

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

		if (ufs.Find(i) == i) {

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

			ans += vec[i][0];

			rem--;

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

				v.push_back(vec[i][j]);

			}

		}

	}

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

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

		ans += v[i];

	}

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

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.520808240021532x):
#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;

}
// Slower C++ solution:
#include<cstdio>

#include<set>

#include<algorithm>

using namespace std;

const int MAXN = 100000;

struct node{

	int num, key, vis;

};

node a[MAXN + 5];

bool operator < (node a, node b) {

	return a.key < b.key;

}

set<node>Set[MAXN + 5];

int fa[MAXN + 5];

int Find(int x) {

	if( fa[x] == x ) return x;

	return fa[x] = Find(fa[x]);

}

int main() {

	int N, M, cnt = 0;

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

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

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

		a[i].num = fa[i] = i;

	}

	int ned = ((N-1) - M) * 2;

	if( ned > N ) {

		printf("Impossible\n");

		return 0;

	}

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

		int u, v;

		scanf("%d%d", &u, &v);

		fa[Find(u)] = Find(v);

	}

	for(int i=0;i<N;i++)

		Set[Find(i)].insert(a[i]);

	long long ans = 0;

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

		if( Find(i) == i ) {

			if( cnt == ned ) continue;

			ans += Set[i].begin()->key;

			a[(*Set[i].begin()).num].vis = true;

			cnt++;

		}

	}

	sort(a, a+N);

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

		if( cnt == ned ) break;

		if( a[i].vis ) continue;

		cnt++;

		ans += a[i].key;

	}

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

}

// Faster C++ solution for the same problem (measured speedup: 6.246143040837342x):
#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;

}
// Slower C++ solution:
#include<cstdio>

#include<vector>

#include<algorithm>

using namespace std;



int a[100001],f[100001];

int ff(int u){

	return f[u]==u?u:f[u]=ff(f[u]);

}

vector<int>g[100001];

int c[100001];

int main(){

	int n,m;

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

	for(int i=1;i<=n;i++)

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

		f[i]=i;

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

		int u,v;

		scanf("%d%d",&u,&v);

		u++;v++;

		f[ff(u)]=ff(v);

	}

	for(int i=1;i<=n;i++)

		g[ff(i)].push_back(a[i]);

	long long ans=0;

	int z=0;

	for(int i=1;i<=n;i++)

		if(i==ff(i)){

			z++;

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

			ans+=g[i][0];

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

				c[++c[0]]=g[i][j];

		}

	if(z==1){

		printf("0\n");

		return 0;

	}

	if(c[0]<z-2){

		printf("Impossible\n");

		return 0;

	}

	sort(c+1,c+c[0]+1);

	for(int i=1;i<=z-2;i++)

		ans+=c[i];

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

}


// Faster C++ solution for the same problem (measured speedup: 3.4500513041842518x):
#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;

}
// Slower C++ solution:
#include<cmath>

#include<cstdio>

#include<algorithm>

#include<queue>

using namespace std;

typedef long long LL;

int n,m;

LL a[100000+10];

int par[100000+10];

priority_queue<LL> mini[100000+10];



int fpar(int x){

	if (par[x]==-1)return x;

	par[x]=fpar(par[x]);

	return par[x];

}

priority_queue <LL > pq1;

LL ans=0;

int main(){

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

	for (int f1=0;f1<n;f1++)scanf("%lld",&a[f1]);

	for (int f1=0;f1<n;f1++){par[f1]=-1;}

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

		int i,j;

		scanf("%d%d",&i,&j);

		i=fpar(i);

		j=fpar(j);

		par[j]=i;

	}

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

		int j=fpar(f1);

		mini[j].push(-a[f1]);

	}

	if (n==1+m){

		printf("0\n");

		return 0;

	}

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

		if (par[f1]==-1){

			ans-=mini[f1].top();

			mini[f1].pop();

			while (!mini[f1].empty()){

				pq1.push(mini[f1].top());

				mini[f1].pop();

			}	

		}

	}

	

	if (int(pq1.size())>=n-m-2){

		for (int f1=1;f1<=n-m-2;f1++){

			ans-=pq1.top();

			pq1.pop();

		}

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

	} else printf("Impossible\n");

}


// Faster C++ solution for the same problem (measured speedup: 4.253870435582735x):
#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;

}
// Slower C++ solution:
#include<cstdio>

#include<set>

#include<algorithm>

using namespace std;

const int MAXN = 100000;

struct node{

	int num, key, vis;

};

node a[MAXN + 5];

bool operator < (node a, node b) {

	return a.key < b.key;

}

set<node>Set[MAXN + 5];

int fa[MAXN + 5];

int Find(int x) {

	if( fa[x] == x ) return x;

	return fa[x] = Find(fa[x]);

}

int main() {

	int N, M, cnt = 0;

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

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

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

		a[i].num = fa[i] = i;

	}

	int ned = ((N-1) - M) * 2;

	if( ned > N ) {

		printf("Impossible\n");

		return 0;

	}

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

		int u, v;

		scanf("%d%d", &u, &v);

		fa[Find(u)] = Find(v);

	}

	for(int i=0;i<N;i++)

		Set[Find(i)].insert(a[i]);

	long long ans = 0;

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

		if( Find(i) == i ) {

			if( cnt == ned ) continue;

			ans += Set[i].begin()->key;

			a[(*Set[i].begin()).num].vis = true;

			cnt++;

		}

	}

	sort(a, a+N);

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

		if( cnt == ned ) break;

		if( a[i].vis ) continue;

		cnt++;

		ans += a[i].key;

	}

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

}

// Faster C++ solution for the same problem (measured speedup: 1.4424615971480892x):
#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cstring>

#include<queue>

#define MX 100005

using namespace std;

typedef pair<int,int> PA;

inline int read()

{

	int x=0,f=1;char c=getchar();

	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}

	while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();

	return x*f;

}

int n,m;

int a[MX],fa[MX],bl[MX],vis[MX];

priority_queue<PA> que[MX];

priority_queue<int> q;

int zbb(int k){return fa[k]==k?k:fa[k]=zbb(fa[k]);}

int main(){

	//freopen("a.in","r",stdin);

	n=read();m=read();

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

		a[i]=read();

	

	for(int i=0;i<n;i++) fa[i]=i;

	

	int x,y,r1,r2;

	for(int i=1;i<=m;i++)

	{

		x=read();y=read();

		r1=zbb(x);r2=zbb(y);

		if(r1!=r2)

			fa[r2]=r1;

	}

	

	int cnt=0;

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

	{

		r1=zbb(i);

		if(!vis[r1])

		{

			vis[r1]=1;

			cnt++;

			bl[r1]=cnt;

		}

		que[bl[r1]].push(make_pair(-a[i],i));

	}

	

	if(cnt==1)

	{

		printf("0\n");

		return 0;

	}

	if(n<cnt*2-2)

	{

		printf("Impossible\n");

		return 0;

	}

	

	long long ans=0;

	for(int i=1;i<=cnt;i++)

	{

		ans-=que[i].top().first;

		que[i].pop();

	}

	

	for(int i=1;i<=cnt;i++)

		while(!que[i].empty())

		{

			q.push(que[i].top().first);

			que[i].pop();

		}

	

	for(int i=1;i<=cnt-2;i++)

	{

		ans-=q.top();q.pop();

	}

	

	cout<<ans<<endl;

	return 0;

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

using namespace std;



typedef long long ll;

const int maxn=100010;

multiset<int> S[maxn];

set<pair<int,int> > S2;

struct Edge

{

	int v,next;

}	e[maxn<<1];

int g[maxn],tot;

void addedge(int x,int y)

{

	tot++;

	e[tot].v=y;

	e[tot].next=g[x];

	g[x]=tot;

}

int n,m;

bool vis[maxn];

int a[maxn];



void dfs(int t,int ha)

{

	S[ha].insert(a[t]);

	vis[t]=true;

	for (int i=g[t];i;i=e[i].next)

	if (!vis[e[i].v])

		dfs(e[i].v,ha);

}

int Union(pair<int,int> x,pair<int,int> y)

{

	multiset<int>::iterator it=S[x.second].lower_bound(x.first);

	S[x.second].erase(it);

	it=S[y.second].lower_bound(y.first);

	S[y.second].erase(it);

	int l=x.second,r=y.second;

	if (S[l].size()>S[r].size())	swap(l,r);

	for (auto i:S[l])

		S[r].insert(i);

	S[l].clear();

	return r;

}

int main()

{

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

	for (int i=1;i<=n;i++)	scanf("%d",&a[i]);

	for (int i=1;i<=m;i++)

	{

		int x,y;

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

		x++;y++;

		addedge(x,y);

		addedge(y,x);

	}

	for (int i=1;i<=n;i++)

	if (!vis[i])

		dfs(i,i);

	for (int i=1;i<=n;i++)

		if (!S[i].empty())

			S2.insert(make_pair(S[i].size(),i));

	ll ans=0;

	for (int i=1;i<=n-1-m;i++)

	{

		if (S2.empty())

		{

			printf("Impossible\n");

			return 0;

		}

		pair<int,int> tmp1=*--S2.end();

		S2.erase(--S2.end());

		if (S2.empty())

		{

			printf("Impossible\n");

			return 0;

		}

		pair<int,int> tmp2=*--S2.end();

		S2.erase(--S2.end());

		tmp1.first=*S[tmp1.second].begin();

		tmp2.first=*S[tmp2.second].begin();

		ans+=tmp1.first+tmp2.first;

		int q=Union(tmp1,tmp2);

		if (!S[q].empty())	S2.insert(make_pair(S[q].size(),q));

	}

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

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.4608248841487645x):
#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cstring>

#include<queue>

#define MX 100005

using namespace std;

typedef pair<int,int> PA;

inline int read()

{

	int x=0,f=1;char c=getchar();

	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}

	while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();

	return x*f;

}

int n,m;

int a[MX],fa[MX],bl[MX],vis[MX];

priority_queue<PA> que[MX];

priority_queue<int> q;

int zbb(int k){return fa[k]==k?k:fa[k]=zbb(fa[k]);}

int main(){

	//freopen("a.in","r",stdin);

	n=read();m=read();

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

		a[i]=read();

	

	for(int i=0;i<n;i++) fa[i]=i;

	

	int x,y,r1,r2;

	for(int i=1;i<=m;i++)

	{

		x=read();y=read();

		r1=zbb(x);r2=zbb(y);

		if(r1!=r2)

			fa[r2]=r1;

	}

	

	int cnt=0;

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

	{

		r1=zbb(i);

		if(!vis[r1])

		{

			vis[r1]=1;

			cnt++;

			bl[r1]=cnt;

		}

		que[bl[r1]].push(make_pair(-a[i],i));

	}

	

	if(cnt==1)

	{

		printf("0\n");

		return 0;

	}

	if(n<cnt*2-2)

	{

		printf("Impossible\n");

		return 0;

	}

	

	long long ans=0;

	for(int i=1;i<=cnt;i++)

	{

		ans-=que[i].top().first;

		que[i].pop();

	}

	

	for(int i=1;i<=cnt;i++)

		while(!que[i].empty())

		{

			q.push(que[i].top().first);

			que[i].pop();

		}

	

	for(int i=1;i<=cnt-2;i++)

	{

		ans-=q.top();q.pop();

	}

	

	cout<<ans<<endl;

	return 0;

}