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: Wrong Answer)

#include <iostream>
#include <vector>
#include <algorithm>
#define llint long long

using namespace std;

llint parent[100005];
llint N, M;
llint a[100005];
vector<llint> cmp[100005];

void init(){
	for(llint i = 0; i < N; i++) parent[i] = i;
}

llint root(llint i)
{
	if(parent[i] == i) return i;
	return parent[i] = root(parent[i]);
}

void unite(llint i, llint j)
{
	llint root_i = root(i), root_j = root(j);
	if(root_i == root_j) return;
	parent[root_i] = root_j;
}

bool same(llint i, llint j)
{
	return root(i) == root(j);
}

int main(void)
{
	cin >> N >> M;
	for(llint i = 0; i < N; i++) cin >> a[i];
	init();
	
	llint x, y;
	for(llint i = 0; i < M; i++){
		cin >> x >> y;
		unite(x, y);
	}
	
	for(llint i = 0; i < N; i++) root(i);
	for(llint i = 0; i < N; i++){
		cmp[parent[i]].push_back(a[i]);
	}
	
	llint cnt = 0, ccnt = 0;
	for(llint i = 0; i < N; i++){
		if(cmp[i].size() == 1) cnt++;
		if(cmp[i].size() > 0) ccnt++;
	}
	
	if(ccnt == 1){
		cout << 0 << endl;
		return 0;
	}
	if(2*(N-M-1) > N){
		cout << "Impossible" << endl;
		return 0;
	}
	
	llint sum = 0;
	for(llint i = 0; i < N; i++){
		if(cmp[i].size() > 0){
			sort(cmp[i].begin(), cmp[i].end());
			sum += cmp[i][0];
		}
	}
	
	vector<llint> vec;
	for(llint i = 0; i < N; i++){
		if(cmp[i].size() > 1){
			for(int j = 1; j < cmp[i].size(); j++) vec.push_back(cmp[i][j]);
		}
	}
	sort(vec.begin(), vec.end());
	
	for(llint i = 0; i < 2*(N-M-1)-N; i++) sum += vec[i];
	cout << sum << endl;
	
	return 0;
}