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<math.h>
#include<limits.h>
#include<iostream>
#include<string>
#include<vector>
#include<stdio.h>
#include<sstream>
#include<list>
#include<queue>
#include<algorithm>
#include<functional>
#include<map>
#include<set>
#include<utility>
#include<initializer_list>
#include<tuple>
#include<regex>
using namespace std;
#define ull unsigned long long
#define ll long long
#define rep(i, n) for(int i=0;i<(int)(n);i++)
#define all(t) t.begin(), t.end()
#define mat(type, row, col, init) vector<vector<type>>(row, vector<type>(col, init));
void dfs(int &n, vector<list<int>>&g, vector<ll>&a, vector<bool>&chd, int &treenum, int node, vector < list<pair<ll, int>>> &t) {
	if (chd[node] == false) {
		chd[node] = true;
		t[treenum].push_back(make_pair(a[node], node));
		for (auto v : g[node]) {
			dfs(n, g, a, chd, treenum, v, t);
		}

	}
}
int main() {
	ll lim = 1e9 + 1;
	int n, m;
	cin >> n >> m;
	if (m == n - 1) {
		cout << 0;
		return 0;
	}
	vector<ll>a(n);
	rep(i, n)cin >> a[i];
	vector<list<int>>g(n);
	rep(i, m) {
		int x, y;
		cin >> x >> y;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	vector < list<pair<ll, int>>> t;
	t.reserve(1e5);
	vector<bool>chd(n, false);
	int treenum = 0;
	rep(i, n) {
		if (chd[i] == false) {
			t.push_back({});
			dfs(n, g, a, chd, treenum, i, t);
			t[treenum].sort();
			treenum++;
		}
	}
	ll ans = 0;
	int usedNum = 0;
	rep(i, treenum) {
		ans += t[i].front().first;
		t[i].pop_front();
		usedNum++;
	}
	priority_queue<ll, vector<ll>, greater<ll> >costbox;
	rep(i, treenum) {
		auto it = t[i].begin();
		while (it != t[i].end()) {
			costbox.push(it->first);
			it++;
		}
	}
	while (usedNum < 2 * (n - m - 1) && !costbox.empty()) {
		auto combiningNode = costbox.top();
		costbox.pop();
		ans += combiningNode;
		usedNum++;

	}
	if (usedNum != 2 * (n - m - 1) )cout << "Impossible";
	else cout << ans;
	return 0;
}