stablegradients/pie-gem5-bysrc huggingface dataset:
// Original C++ solution (slower):
#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;

}


// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

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

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

#define pq priority_queue

#define P pair<int,int>

#define P2 pair<int,P>

#define P3 pair<int,P2>

typedef long long ll; typedef long double ld;

using namespace std;

const int INF=1e9, MOD=1e9+7, around[]={0,1,1,-1,-1,0,-1,1,0,0};

const ll LINF=1e18;

const ld PI=abs(acos(-1));

set<int> st;

vector<ll> vec[100010], pos[100010];

vector<ll> g[100010];



void dfs(int p, int q){

	if(st.count(p)) return ; st.insert(p);

	vec[q].push_back(p);

	

	for(auto e:g[p]) dfs(e, q);

}



int main(){

	ll n, m, a[100010];

	cin >> n >> m;

	REP(i,0,n) cin >> a[i];

	REP(i,0,m){

		int x, y; cin >> x >> y;

		g[x].push_back(y);

		g[y].push_back(x);

	}

	

	pq<P2, vector<P2>, greater<P2>> qu;

	ll cou = 0, count = 0, li[100010]; ll s = 0, ma = 0;

	REP(i,0,n) if(!st.count(i)) dfs(i, cou++);

	REP(i,0,cou) REP(j,0,vec[i].size()) pos[i].push_back(a[vec[i][j]]);

	REP(i,0,cou) sort(pos[i].begin(), pos[i].end());

	REP(i,0,cou) s += pos[i][0];

	REP(i,0,cou) REP(j,1,pos[i].size()) qu.push({pos[i][j], {i, j}});

	

	int c = cou - 2;

	while(c and !qu.empty()){

		s += qu.top().first;

		ma = max<int>(ma, qu.top().first);

		qu.pop();

		c--;

	}

	if(cou == 1) cout << 0 << endl;

	else if(c) cout << "Impossible" << endl;

	else cout << s << endl;

	return 0;

}


// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

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

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

#define pq priority_queue

#define P pair<int,int>

#define P2 pair<int,P>

#define P3 pair<int,P2>

typedef long long ll; typedef long double ld;

using namespace std;

const int INF=1e9, MOD=1e9+7, around[]={0,1,1,-1,-1,0,-1,1,0,0};

const ll LINF=1e18;

const ld PI=abs(acos(-1));



int num[100010];

vector<int> g[100010];

vector<int> vec[100010];

set<int> st;



void dfs(int p, int q){

	if(st.count(p)) return ; st.insert(p);

	vec[q].push_back(num[p]);

	

	for(auto e:g[p]) dfs(e, q);

}



int main(){

	int n,m; cin >> n >> m;

	REP(i,0,n) cin >> num[i];

	REP(i,0,m){

		int a,b; cin >> a >> b;

		g[a].push_back(b);

		g[b].push_back(a);

	}

	

	int cou = 0; ll s = 0;

	pq<int, vector<int>, greater<int>> qu;

	REP(i,0,n) if(!st.count(i)) dfs(i, cou++);

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

	REP(i,0,cou) s += vec[i][0];

	REP(i,0,cou) REP(j,1,vec[i].size()) qu.push(vec[i][j]);

	

	int count = cou - 2;

	while(count and !qu.empty()){

		s += qu.top(); qu.pop();

		count--;

	}

	

	if(cou == 1) cout << 0 << endl;

	else if(count) cout << "Impossible" << endl;

	else cout << s << endl;

	return 0;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
//左手拈着花，右手舞着剑 

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<cstring>

#include<map>

#include<vector>

#include<queue>

#define ll long long

#define pi pair<int,int>

#define mp(a,b) make_pair(a,b)

using namespace std;

const int N=100005;priority_queue

<pi,vector<pi>,greater<pi> >q[N];

int val[N],fa[N],rk[N],n,m,k;vector<pi>v;

void take(){

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

	fa[i]=i,rk[i]=0;

} int get(int x){

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

} void merge(int x,int y){

	x=get(x);y=get(y);

	if(x==y) return ;

	if(rk[x]<rk[y]) fa[x]=y;

	else{

		fa[y]=x;if(rk[x]==rk[y]) rk[x]++;

	}

} int main(){

	ll ans=0;scanf("%d%d",&n,&m);take();

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

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

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

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

		if(fx!=fy) merge(fx,fy);

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

	q[get(i)].push(mp(val[i],i));

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

	if(!q[i].empty()) v.push_back(q[i].top()),

	val[q[i].top().second]=2e9,

	ans+=q[i].top().first;

	if(v.size()==1) puts("0");

	else if(n<(v.size()-1)*2)

	puts("Impossible");else{

		sort(val,val+n);

		n=(v.size()-1)*2-v.size();

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

		cout<<ans<<endl; 

	} return 0;

}

// Optimized solution to the same problem (faster):
#pragma GCC optimize(2)

#include<bits/stdc++.h>

#define N 100005

#define int long long

using namespace std;



#define v1 first

#define v2 second

#define pb push_back

#define mid ((l+r)>>1)

#define vec vector<int>

#define pr pair<int,int>

#define tp tuple<int,int,int>

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

#define all(x) x.begin(),x.end()

#define mem(a,x) memset(a,x,sizeof a)

#define For(x) for(int y,i=head[x];(y=e[i].to);i=e[i].nxt)



inline bool rd(int &X)

{

    X=0;int w=0;char ch=0;

    while(!isdigit(ch))w|=ch=='-',ch=getchar();

    while( isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();

    X=w?-X:X; return 1;

}



vec now;

int n,m,tot,ans;

int a[N],vis[N],u[N];

int head[N],cnt,mn[N];

struct nd{int nxt,to;}e[N<<1];

#define For(x) for(int y,i=head[x];(y=e[i].to);i=e[i].nxt)



void add(int x,int y){

    e[++cnt]=(nd){head[x],y};head[x]=cnt;

    e[++cnt]=(nd){head[y],x};head[y]=cnt;

}

void dfs(int x){

    if(a[x]<a[mn[tot]]) mn[tot]=x;

    For(x) if(!vis[y])

        vis[y]=1,dfs(y);

}

signed main()

{

    rd(n);rd(m); a[0]=2e9;



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

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

        rd(x),rd(y),add(x+1,y+1);

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

        if(!vis[i]) ++tot,dfs(i);

    if(tot==1) return cout<<0,0;

    if(n<2*(tot-1)) return cout<<"Impossible",0;

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

        u[mn[i]]=1,ans+=a[mn[i]];

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

        if(!u[i]) now.pb(a[i]);

    sort(all(now));

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

        ans+=now[i-1];

    cout<<ans;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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);

}

// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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);

}


// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}

// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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);

}


// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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");

}


// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem: