stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include<bits/stdc++.h>

#define rep(i,a,b) for (int i=(a); i<=(b); i++)

#define per(i,a,b) for (int i=(a); i>=(b); i--)

using namespace std;



const int maxn = 100005;

int a[maxn], vis[maxn], n, m, x, y, mn, cur;

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

vector<int> e[maxn];

long long ans;



void dfs(int u) {

	int sz = e[u].size();

	if (a[u] < mn) mn = a[u], cur = u;

	vis[u] = 1;

	if (!sz) return;

	rep (i, 0, sz - 1)

		if (!vis[e[u][i]]) dfs(e[u][i]);

}



int main() {

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

	if (n < 2 * (n - m - 1)) 

		return puts("Impossible"), 0;

	if (n - 1 == m)

		return puts("0"), 0;

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

	rep (i, 1, m) {

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

		e[x].push_back(y); e[y].push_back(x);

	}

	rep (i, 1, n)

		if (!vis[i]) {

			mn = 2e9;

			dfs(i);

			ans += mn;

			a[cur] = 0;

		}

	rep (i, 1, n)

		if (a[i]) Q.push(a[i]);

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

	while (m-- > 0) {

		ans += Q.top();

		Q.pop();

	}

	cout << ans << endl;

	return 0;

}

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

#include<algorithm>

#include<cstdio>

#include<cstdlib>

#include<cmath>

#include<cstring>

#include<queue>

#include<vector>

#include<map>

using namespace std;

#define llg long long

#define maxn 200010

#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);



inline llg getint()

{

    llg w=0,q=0; char c=getchar();

    while((c<'0' || c>'9') && c!='-') c=getchar();

    if (c=='-')  q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();

    return q ? -w : w;

}



struct node{llg val,fa;} a[maxn];



bool cmp(const node &a,const node&b){return a.val<b.val;}



llg n,m,fa[maxn],ans,c[maxn],needb,xian[maxn],chuxian[maxn],bj[maxn];



llg find(llg x) {if (fa[x]!=x) fa[x]=find(fa[x]); return fa[x];}



int main()

{

	cin>>n>>m;

	for (llg i=1;i<=n;i++) c[i]=getint(),fa[i]=i;

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

	{

		llg x=getint(),y=getint();

		x++,y++;

		if (find(x)!=find(y)) fa[find(x)]=find(y);

	}

	for (llg i=1;i<=n;i++) a[i].val=c[i],a[i].fa=find(i);

	sort(a+1,a+n+1,cmp);

	needb=n-1-m;

	llg cs=0;

	for (llg i=1;i<=n && cs<needb*2;i++)

		if (!chuxian[a[i].fa])

		{

			cs++;

			bj[i]=1;

			chuxian[a[i].fa]=1;

			ans+=a[i].val;

		}

	for (llg i=1;i<=n && cs<needb*2;i++)

	{

		if (xian[a[i].fa]<needb && !bj[i])

		{

			xian[a[i].fa]++;

			ans+=a[i].val;

			cs++;

		}

	}

	if (cs<needb*2) puts("Impossible"); else 

	cout<<ans;

	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.260400241890338x):
#include <bits/stdc++.h>





using namespace std;

typedef long long LL;

const int maxn = 100005;

int a[maxn], fa[maxn], mi[maxn], id[maxn], vis[maxn];

int n, m;



void Init()

{

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

    {

        fa[i] = i;

        mi[i] = a[i];

        id[i] = i;

    }

}



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);

    fa[fx] = fy;

    if(mi[fy] > mi[fx])

    {

        mi[fy] = mi[fx];

        id[fy] = id[fx];

    }

}



int main()

{

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

    multiset<int> s;

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

    {

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

        s.insert(a[i]);

    }

    Init();

//    multiset<int>::iterator it;

//    for(it = s.begin(); it != s.end(); it++)

//    {

//        printf("%d ", *it);

//    }

//    printf("\n");

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

    {

        int u, v;

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

        Merge(u + 1, v + 1);

    }

    int num = 0;

    LL ans = 0;

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

    {

//        printf("%d %d %d\n", i, Find(i), mi[fa[i]]);

        if(Find(i) == i)

        {

            num++;

            ans += mi[fa[i]];

            multiset<int>::iterator it = s.find(mi[fa[i]]);

            s.erase(it);

        }

    }

    if(n < 2 * num - 2)

        printf("Impossible\n");

    else if(num == 1)

        printf("0\n");

    else

    {

        int cnt = 0;

        multiset<int>::iterator it;

        for(it = s.begin(); it != s.end() && cnt < num - 2; it++)

        {

            cnt++;

            ans += *it;

        }

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

    }

    return 0;

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



using namespace std;



#define SZ(x) ((int)x.size())



const int N = 100005;



int n, m;

int a[N];

int fa[N];



vector<int> val[N];



int getfa(int x) {

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

}



void merge(int x, int y) {

	x = getfa(x);

	y = getfa(y);

	if(SZ(val[x]) < SZ(val[y])) {

		swap(x, y);

	}

	for(auto v: val[y]) {

		val[x].push_back(v);

	}

	val[y].clear();

	fa[y] = x;

}



void input()

{

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

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

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



		val[i].push_back(a[i]);

		fa[i] = i;

	}

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

		int x, y;

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

		x++, y++;

		merge(x, y);

	}

}



void solve()

{

	long long ans = 0;



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



	if(cnt == 0) {

		puts("0");

		return;

	}



	vector<int> vec;

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

		if(fa[i] == i) {

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

			ans += val[i][0];

			cnt--;

			for(int j = 1; j < SZ(val[i]); j++) {

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

			}

		}

	}



	if(SZ(vec) < cnt) {

		puts("Impossible");

		return;

	}



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

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

		ans += vec[i];

	}

	cout << ans << endl;

}



int main()

{

	input();

	solve();



	return 0;

}


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





using namespace std;

typedef long long LL;

const int maxn = 100005;

int a[maxn], fa[maxn], mi[maxn], id[maxn], vis[maxn];

int n, m;



void Init()

{

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

    {

        fa[i] = i;

        mi[i] = a[i];

        id[i] = i;

    }

}



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);

    fa[fx] = fy;

    if(mi[fy] > mi[fx])

    {

        mi[fy] = mi[fx];

        id[fy] = id[fx];

    }

}



int main()

{

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

    multiset<int> s;

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

    {

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

        s.insert(a[i]);

    }

    Init();

//    multiset<int>::iterator it;

//    for(it = s.begin(); it != s.end(); it++)

//    {

//        printf("%d ", *it);

//    }

//    printf("\n");

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

    {

        int u, v;

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

        Merge(u + 1, v + 1);

    }

    int num = 0;

    LL ans = 0;

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

    {

//        printf("%d %d %d\n", i, Find(i), mi[fa[i]]);

        if(Find(i) == i)

        {

            num++;

            ans += mi[fa[i]];

            multiset<int>::iterator it = s.find(mi[fa[i]]);

            s.erase(it);

        }

    }

    if(n < 2 * num - 2)

        printf("Impossible\n");

    else if(num == 1)

        printf("0\n");

    else

    {

        int cnt = 0;

        multiset<int>::iterator it;

        for(it = s.begin(); it != s.end() && cnt < num - 2; it++)

        {

            cnt++;

            ans += *it;

        }

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

    }

    return 0;

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

#include<cstring>

#include<algorithm>

#include<queue>

#define ll long long

#define MN 200005

using namespace std;

inline ll in(){

    ll x=0;bool f=0;char c;

    for (;(c=getchar())<'0'||c>'9';f=c=='-');

    for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');

    return f?-x:x;

}

priority_queue<ll,vector<ll>,greater<ll> >q;

struct edge{

	int to,nxt;

}e[MN<<1];

ll a[MN],mn[MN],res;

int num[MN],h[MN];

int n,m,x,y,cnt,tot,ct;

bool vis[MN],tmp[MN];

inline void ins(int x,int y){

	e[++cnt].to=y;e[cnt].nxt=h[x];h[x]=cnt;

}

inline void dfs(int u){

	mn[tot]=min(mn[tot],a[u]);

	for (int i=h[u];i;i=e[i].nxt){

		int v=e[i].to;

		if (vis[v]) continue;

		vis[v]=1;num[v]=tot;dfs(v);

	}

}

int main()

{

	n=in();m=in();

	memset(mn,0x3f,sizeof(mn));

	for (int i=1;i<=n;++i) a[i]=in();

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

		x=in()+1;y=in()+1;

		ins(x,y);ins(y,x);

	}

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

	if (!vis[i]){

		vis[i]=1;num[i]=(++tot);dfs(i);

	}

	if (tot==1) {printf("0");return 0;}

	for (int i=1;i<=tot;++i) res+=1ll*mn[i];

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

		if (!tmp[num[i]]&&a[i]==mn[num[i]]) {tmp[num[i]]=1;continue;}

		else q.push(a[i]);

	}

	while (!q.empty()){

		if (ct==tot-2) break;

		ll x=q.top();q.pop();++ct;res+=1ll*x;

	} 

	if (ct==tot-2) printf("%lld",res);else printf("Impossible");

	return 0;

}

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





using namespace std;

typedef long long LL;

const int maxn = 100005;

int a[maxn], fa[maxn], mi[maxn], id[maxn], vis[maxn];

int n, m;



void Init()

{

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

    {

        fa[i] = i;

        mi[i] = a[i];

        id[i] = i;

    }

}



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);

    fa[fx] = fy;

    if(mi[fy] > mi[fx])

    {

        mi[fy] = mi[fx];

        id[fy] = id[fx];

    }

}



int main()

{

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

    multiset<int> s;

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

    {

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

        s.insert(a[i]);

    }

    Init();

//    multiset<int>::iterator it;

//    for(it = s.begin(); it != s.end(); it++)

//    {

//        printf("%d ", *it);

//    }

//    printf("\n");

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

    {

        int u, v;

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

        Merge(u + 1, v + 1);

    }

    int num = 0;

    LL ans = 0;

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

    {

//        printf("%d %d %d\n", i, Find(i), mi[fa[i]]);

        if(Find(i) == i)

        {

            num++;

            ans += mi[fa[i]];

            multiset<int>::iterator it = s.find(mi[fa[i]]);

            s.erase(it);

        }

    }

    if(n < 2 * num - 2)

        printf("Impossible\n");

    else if(num == 1)

        printf("0\n");

    else

    {

        int cnt = 0;

        multiset<int>::iterator it;

        for(it = s.begin(); it != s.end() && cnt < num - 2; it++)

        {

            cnt++;

            ans += *it;

        }

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

    }

    return 0;

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

#define rep(i,a,b) for (int i=(a); i<=(b); i++)

#define per(i,a,b) for (int i=(a); i>=(b); i--)

using namespace std;



const int maxn = 100005;

int a[maxn], vis[maxn], n, m, x, y, mn, cur;

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

vector<int> e[maxn];

long long ans;



void dfs(int u) {

	int sz = e[u].size();

	if (a[u] < mn) mn = a[u], cur = u;

	vis[u] = 1;

	if (!sz) return;

	rep (i, 0, sz - 1)

		if (!vis[e[u][i]]) dfs(e[u][i]);

}



int main() {

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

	if (n < 2 * (n - m - 1)) 

		return puts("Impossible"), 0;

	if (n - 1 == m)

		return puts("0"), 0;

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

	rep (i, 1, m) {

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

		e[x].push_back(y); e[y].push_back(x);

	}

	rep (i, 1, n)

		if (!vis[i]) {

			mn = 2e9;

			dfs(i);

			ans += mn;

			a[cur] = 0;

		}

	rep (i, 1, n)

		if (a[i]) Q.push(a[i]);

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

	while (m-- > 0) {

		ans += Q.top();

		Q.pop();

	}

	cout << ans << endl;

	return 0;

}

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





using namespace std;

typedef long long LL;

const int maxn = 100005;

int a[maxn], fa[maxn], mi[maxn], id[maxn], vis[maxn];

int n, m;



void Init()

{

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

    {

        fa[i] = i;

        mi[i] = a[i];

        id[i] = i;

    }

}



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);

    fa[fx] = fy;

    if(mi[fy] > mi[fx])

    {

        mi[fy] = mi[fx];

        id[fy] = id[fx];

    }

}



int main()

{

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

    multiset<int> s;

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

    {

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

        s.insert(a[i]);

    }

    Init();

//    multiset<int>::iterator it;

//    for(it = s.begin(); it != s.end(); it++)

//    {

//        printf("%d ", *it);

//    }

//    printf("\n");

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

    {

        int u, v;

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

        Merge(u + 1, v + 1);

    }

    int num = 0;

    LL ans = 0;

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

    {

//        printf("%d %d %d\n", i, Find(i), mi[fa[i]]);

        if(Find(i) == i)

        {

            num++;

            ans += mi[fa[i]];

            multiset<int>::iterator it = s.find(mi[fa[i]]);

            s.erase(it);

        }

    }

    if(n < 2 * num - 2)

        printf("Impossible\n");

    else if(num == 1)

        printf("0\n");

    else

    {

        int cnt = 0;

        multiset<int>::iterator it;

        for(it = s.begin(); it != s.end() && cnt < num - 2; it++)

        {

            cnt++;

            ans += *it;

        }

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

    }

    return 0;

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



typedef long long LL;



const int MAXN = 1e5 + 5;



int n, m, w[MAXN];



std::multiset<int> st[MAXN];

std::set<std::pair<int, int> > spec;



int fa[MAXN], part;



int Find(int x) {

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

}



void merge(int u, int v) {

    if (Find(u) == Find(v)) return;

    if (st[fa[u]].size() > st[fa[v]].size()) std::swap(u, v);

    --part;

    for (int i: st[fa[u]]) {

        st[fa[v]].insert(i);

    }

    st[fa[u]].clear();

    if (!st[fa[v]].empty()) spec.insert(std::make_pair(st[fa[v]].size(), fa[v]));

    fa[fa[u]] = fa[v];

}



int main() {

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

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

        fa[i] = i;

        scanf("%d", w + i);

        st[i].insert(w[i]);

        spec.insert(std::make_pair(1, i));

    }

    

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

        static int u, v;

        

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

        spec.erase(spec.find(std::make_pair(st[Find(u)].size(), Find(u))));

        spec.erase(spec.find(std::make_pair(st[Find(v)].size(), Find(v))));

        merge(u, v);

    }

    

    LL ans = 0;

    

    while (part > 1) {

        if (spec.size() < 2) {

            puts("Impossible");

            return 0;

        }

        auto x = *--spec.end();

        spec.erase(--spec.end());

        

        auto y = *--spec.end();

        spec.erase(--spec.end());

        

        int u = x.second, v = y.second;

        ans += *st[Find(u)].begin() + *st[Find(v)].begin();

        

        st[Find(u)].erase(st[Find(u)].begin());

        st[Find(v)].erase(st[Find(v)].begin());

        

        merge(u, v);

    }

    

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

    

    return 0;

}

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

#include<algorithm>

using namespace std;

typedef long long ll;

int p[100100];

ll ans;

int n, m;

pair<ll, int> a[100100];

bool group_used[100100];

bool used[100100];

int root(int x) { return x == p[x] ? x : p[x] = root(p[x]); }

int main()

{

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

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

	{

		ll cost;

		scanf("%lld", &cost);

		a[i] = make_pair(cost, i);

	}

	for (int i = 1; i <= n; i++) p[i] = i;

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

	{

		int u, v;

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

		u++; v++;

		p[root(u)] = root(v);

	}

	int g = 0;

	for (int i = 1; i <= n; i++) if (p[i] == i) g++;

	// need to group g supernodes into a tree. need to have:

	//   sum of degree = 2(g-1) <= number of nodes = n

	if (2 * (g - 1) > n)

	{

		printf("Impossible\n");

		return 0;

	}

	// select smallest cost from each group first

	// then select smallest from rest

	sort(&a[1], &a[n + 1]);

	int dsum = 0;

	for (int i = 1; i <= n && dsum < 2 * (g - 1); i++)

	{

		int x = a[i].second;

		int r = root(x);

		if (group_used[r] || used[x]) continue;

		group_used[r] = used[x] = true;

		ans += a[i].first;

		dsum++;

	}

	for (int i = 1; i <= n && dsum < 2 * (g - 1); i++)

	{

		int x = a[i].second;

		if (used[x]) continue;

		ans += a[i].first;

		dsum++;

	}

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

	return 0;

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

#include <iostream>

#include <cstdlib>

#include <cstdio>

#include <string>

#include <vector>

using namespace std;

const int MAXN = 100000;



int n, m;

int fa[MAXN+5];

int val[MAXN+5];

vector <int> blk[MAXN+5];

vector <int> ansEdge;

long long int ans;



int SetFind(int x)

{

    if(fa[x] != x)

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

    return fa[x];

}



void SetInit(int n)

{

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

        fa[i] = i;

}



int main()

{

    int blkcnt;



    cin >> n >> m ;

    SetInit(n);

    blkcnt = n;



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

    {

        cin >> val[i] ;

        //blk[i].push_back(val[i]);

    }





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

    {

        int u, v;

        cin >> u >> v;

        u++, v++;

        if(SetFind(u) != SetFind(v))

            fa[SetFind(u)] = SetFind(v), blkcnt--;

    }



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

        blk[SetFind(i)].push_back(val[i]);

/*

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

    {

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

            cout << blk[i].size() << endl ;

    }

*/

    if(blkcnt <= 1)

    {

        cout << 0 << endl ;

        return 0;

    }



    blkcnt -= 2;



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

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

        {

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

            ans += blk[i][0];

            for(int k = 1; k < blk[i].size(); k++)

                ansEdge.push_back(blk[i][k]);

        }



    if(ansEdge.size() < blkcnt)

    {

        cout << "Impossible" << endl;

        return 0;

    }



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



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

        ans += ansEdge[i] ;



    cout << ans << endl ;

    return 0;

}


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

#include<algorithm>

using namespace std;

typedef long long ll;

int p[100100];

ll ans;

int n, m;

pair<ll, int> a[100100];

bool group_used[100100];

bool used[100100];

int root(int x) { return x == p[x] ? x : p[x] = root(p[x]); }

int main()

{

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

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

	{

		ll cost;

		scanf("%lld", &cost);

		a[i] = make_pair(cost, i);

	}

	for (int i = 1; i <= n; i++) p[i] = i;

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

	{

		int u, v;

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

		u++; v++;

		p[root(u)] = root(v);

	}

	int g = 0;

	for (int i = 1; i <= n; i++) if (p[i] == i) g++;

	// need to group g supernodes into a tree. need to have:

	//   sum of degree = 2(g-1) <= number of nodes = n

	if (2 * (g - 1) > n)

	{

		printf("Impossible\n");

		return 0;

	}

	// select smallest cost from each group first

	// then select smallest from rest

	sort(&a[1], &a[n + 1]);

	int dsum = 0;

	for (int i = 1; i <= n && dsum < 2 * (g - 1); i++)

	{

		int x = a[i].second;

		int r = root(x);

		if (group_used[r] || used[x]) continue;

		group_used[r] = used[x] = true;

		ans += a[i].first;

		dsum++;

	}

	for (int i = 1; i <= n && dsum < 2 * (g - 1); i++)

	{

		int x = a[i].second;

		if (used[x]) continue;

		ans += a[i].first;

		dsum++;

	}

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

	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: 22.226621149420854x):
#include<cstdio>

#include<algorithm>

using namespace std;

typedef long long ll;

int p[100100];

ll ans;

int n, m;

pair<ll, int> a[100100];

bool group_used[100100];

bool used[100100];

int root(int x) { return x == p[x] ? x : p[x] = root(p[x]); }

int main()

{

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

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

	{

		ll cost;

		scanf("%lld", &cost);

		a[i] = make_pair(cost, i);

	}

	for (int i = 1; i <= n; i++) p[i] = i;

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

	{

		int u, v;

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

		u++; v++;

		p[root(u)] = root(v);

	}

	int g = 0;

	for (int i = 1; i <= n; i++) if (p[i] == i) g++;

	// need to group g supernodes into a tree. need to have:

	//   sum of degree = 2(g-1) <= number of nodes = n

	if (2 * (g - 1) > n)

	{

		printf("Impossible\n");

		return 0;

	}

	// select smallest cost from each group first

	// then select smallest from rest

	sort(&a[1], &a[n + 1]);

	int dsum = 0;

	for (int i = 1; i <= n && dsum < 2 * (g - 1); i++)

	{

		int x = a[i].second;

		int r = root(x);

		if (group_used[r] || used[x]) continue;

		group_used[r] = used[x] = true;

		ans += a[i].first;

		dsum++;

	}

	for (int i = 1; i <= n && dsum < 2 * (g - 1); i++)

	{

		int x = a[i].second;

		if (used[x]) continue;

		ans += a[i].first;

		dsum++;

	}

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

	return 0;

}