stablegradients/pie-gem5-pairs huggingface dataset:
// 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.8104493209309573x):
#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);

}
// 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.8334972832102747x):
#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);

}
// 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.468343508676161x):
#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");

}
// 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.4870362858833386x):
#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");

}
// 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.2945219005835473x):
#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

*/
// 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.451225105949279x):
#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 <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.5259905008813317x):
#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<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.255336708994926x):
#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<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.455129418247591x):
#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;

}