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>
using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<int, P> P1;
typedef pair<P, P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i, x) for (long long i = 0; i < x; i++)
#define repn(i, x) for (long long i = 1; i <= x; i++)
#define SORT(x) sort(x.begin(), x.end())
#define ERASE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define POSL(x, v) (lower_bound(x.begin(), x.end(), v) - x.begin())
#define POSU(x, v) (upper_bound(x.begin(), x.end(), v) - x.begin())
vector<pair<string, P>> vec;
// vector<vector<int>> data(3, vector<int>(4));

const string NO = "Impossible";

struct uf_tree {
    std::vector<int> parent;
    int __size;
    uf_tree(int size_) : parent(size_, -1), __size(size_) {}
    void unite(int x, int y) {
        if ((x = find(x)) != (y = find(y))) {
            if (parent[y] < parent[x]) std::swap(x, y);
            parent[x] += parent[y];
            parent[y] = x;
            __size--;
        }
    }
    bool is_same(int x, int y) { return find(x) == find(y); }
    int find(int x) { return parent[x] < 0 ? x : parent[x] = find(parent[x]); }
    int size(int x) { return -parent[find(x)]; }
    int size() { return __size; }
};

void solve(long long N, long long M, std::vector<long long> a, std::vector<long long> x, std::vector<long long> y) {
    if (M == 0) {
        if (N == 1) cout << "0" << endl;
        if (N == 2) cout << a[0] + a[1] << endl;
        if (N >= 3) cout << NO << endl;
        return;
    }
    vector<pair<ll, ll>> v(N);
    rep(i, N) { v[i] = make_pair(a[i], i); }
    SORT(v);

    uf_tree ut(N);
    rep(i, M) { ut.unite(x[i], y[i]); }
    vector<bool> used(N);

    ll i = 0;
    ll res = 0;
    rep(i, N) {
        for (ll j = i + 1; j < N; j++) {
            ll id1 = v[i].second, id2 = v[j].second;
            if (used[id1] || ut.size(id1) == 1) break;
            if (ut.size(id2) == 1) continue;
            if (!ut.is_same(id1, id2) && !used[id2]) {
                res += v[i].first + v[j].first;
                i = j;
                used[id1] = true;
                used[id2] = true;
                ut.unite(id1, id2);
                break;
            }
            if (j == N - 1) i = j;
        }
    }
    ll b = 0, c = 0;
    rep(i, N) {
        if (ut.size(i) == 1)
            b++;
        else if (!used[i])
            c++;
    }

    if (c < b) {
        cout << NO << endl;
        return;
    }

    ll d = 0;
    rep(i, N) {
        ll id = v[i].second;
        if (ut.size(id) == 1) res += v[i].first;
        if (!used[id] && d < b) {
            res += v[i].first;
            d++;
        }
    }

    cout << res << endl;
}

int main() {
    long long N;
    scanf("%lld", &N);
    long long M;
    scanf("%lld", &M);
    std::vector<long long> a(N - 1 - 0 + 1);
    for (int i = 0; i < N - 1 - 0 + 1; i++) {
        scanf("%lld", &a[i]);
    }
    std::vector<long long> x(M);
    std::vector<long long> y(M);
    for (int i = 0; i < M; i++) {
        scanf("%lld", &x[i]);
        scanf("%lld", &y[i]);
    }
    solve(N, M, std::move(a), std::move(x), std::move(y));
    return 0;
}