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 <bits/stdc++.h>
#define ALL(A) (A).begin(),(A).end()
#define ll long long
#define rep(i,n) for(int i=0;i<(n);i++)

const ll mod = 1e9+7;
const ll INF = -1*((1LL<<63)+1);
const int inf = -1*((1<<31)+1);

using namespace std;

struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    vector<int> count; //それぞれ何個の島を辿れるか

    UnionFind(int N) : par(N+1), count(N+1) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) par[i] = i, count[i] = 1;
    }

    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }

    int size(int x) {
        return count[root(x)]; 
    }

    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        if (size(rx) < size(ry)) swap(rx, ry);
        count[rx] += count[ry]; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
        par[ry] = rx;
    }

    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }

};


int main(void){
	cin.tie(0);
	ios::sync_with_stdio(false);
	ll N,M;
    cin >> N >> M;
    vector<ll> a(N);
    vector<vector<ll>> cost(N);
    UnionFind uni(N);
    rep(i,N)cin >> a[i];
    rep(i,M){
        int x,y;
        cin >> x >> y;
        uni.unite(x,y);
    }
    rep(i,N){
        int par = uni.root(i);
        cost[par].push_back(a[i]);
    }
    rep(i,N)sort(ALL(cost[i]));
    int par = uni.root(0);
    ll ans = 0;
    for(int i=0;i<N;i++){
        if(uni.root(i)!=par){
            //iとparをつなげる必要がある
            if(cost[uni.root(par)].size() == 0 || cost[uni.root(i)].size() == 0){
                cout << "Impossible" << endl;
                return 0;
            }

            ans += cost[uni.root(par)][0] + cost[uni.root(i)][0];
            uni.unite(par,i);
            if(cost[uni.root(par)].size()>1)cost[uni.root(par)].erase(cost[uni.root(par)].begin());
            else cost[uni.root(par)].clear();
            if(cost[uni.root(i)].size()>1)cost[uni.root(i)].erase(cost[uni.root(i)].begin());
            else cost[uni.root(i)].clear();
            cost[uni.root(par)].insert(std::end(cost[uni.root(par)]), std::begin(cost[uni.root(i)]), std::end(cost[uni.root(i)]));
            sort(ALL(cost[uni.root(par)]));
        }
    }
    cout << ans << endl;
}