Problem:
Score : 600 points

Problem Statement

You are given a forest with N vertices and M edges. The vertices are numbered 0 through N-1.
The edges are given in the format (x_i,y_i), which means that Vertex x_i and y_i are connected by an edge.

Each vertex i has a value a_i.
You want to add edges in the given forest so that the forest becomes connected.
To add an edge, you choose two different vertices i and j, then span an edge between i and j.
This operation costs a_i + a_j dollars, and afterward neither Vertex i nor j can be selected again.

Find the minimum total cost required to make the forest connected, or print Impossible if it is impossible.

Constraints

1 ≤ N ≤ 100,000

0 ≤ M ≤ N-1

1 ≤ a_i ≤ 10^9

0 ≤ x_i,y_i ≤ N-1

The given graph is a forest.

All input values are integers.

Input

Input is given from Standard Input in the following format:

N M
a_0 a_1 .. a_{N-1}
x_1 y_1
x_2 y_2
:
x_M y_M

Output

Print the minimum total cost required to make the forest connected, or print Impossible if it is impossible.

Sample Input 1

7 5
1 2 3 4 5 6 7
3 0
4 0
1 2
1 3
5 6

Sample Output 1

7

If we connect vertices 0 and 5, the graph becomes connected, for the cost of 1 + 6 = 7 dollars.

Sample Input 2

5 0
3 1 4 1 5

Sample Output 2

Impossible

We can't make the graph connected.

Sample Input 3

1 0
5

Sample Output 3

0

The graph is already connected, so we do not need to add any edges.

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<ll,int> P;

int n,m;
ll a[100001];
vector<int> G[100001];
int cmp[100001];

struct quickfind{
	int par[200005];
	priority_queue<ll,vector<ll>,greater<ll> > qi[200005];
	quickfind(){
	}
	void init(int n){
		for(int i=0;i<n;i++){
			par[i]=i;
		}
	}
	int find(int x){
		if(par[x]==x)return x;
		return par[x]=find(par[x]);
	}

	void insert(int x,int y){
		qi[x].push(y);
	}

	void unite(int x,int y){
		x=find(x);
		y=find(y);
		if(x==y)return;
		if(qi[x].size()<qi[y].size()){
			par[x]=y;
			while(qi[x].size()){
				ll v=qi[x].top();
				qi[x].pop();
				qi[y].push(v);
			}
		}else{
			par[y]=x;
			while(qi[y].size()){
				ll v=qi[y].top();
				qi[y].pop();
				qi[x].push(v);
			}
		}
	}

	bool same(int x,int y){
		return find(x)==find(y);
	}
};

quickfind qui;

void dfs(int v,int c){
	cmp[v]=c;
	qui.qi[c].push(a[v]);
	for(int i=0;i<G[v].size();i++){
		if(cmp[G[v][i]]==-1){
			dfs(G[v][i],c);
		}
	}
}

int main(void){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		scanf("%lld",&a[i]);
	}
	for(int i=0;i<m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	memset(cmp,-1,sizeof(cmp));
	int cnt=0;
	for(int i=0;i<n;i++){
		if(cmp[i]==-1)dfs(i,cnt++);
	}
	if(cnt==1){
		puts("0");
		return 0;
	}
	priority_queue<ll,vector<ll>,greater<ll> > pl;
	ll ans=0;
	int ct=0;
	for(int i=0;i<cnt;i++){
		if(qui.qi[i].size()>=2){
			ans+=qui.qi[i].top();
			qui.qi[i].pop();
			while(qui.qi[i].size()){
				pl.push(qui.qi[i].top());
				qui.qi[i].pop();
			}
		}
		else{
			ans+=qui.qi[i].top();
			ct++;
		}
	}
	for(int i=0;i<cnt-2;i++){
		if(pl.size()==0){
			printf("Impossible\n");
			return 0;
		}
		ans+=pl.top();
		pl.pop();
	}
	printf("%lld\n",ans);
	return 0;
}