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;

using ll = long long;
using pii = pair<int, int>;

constexpr int INF = 1e9;
constexpr ll INFLL = 1e18;

constexpr int dx[4] = {0, 1, 0, -1};
constexpr int dy[4] = {-1, 0, 1, 0};

template <typename T>
class skew_heap {
    struct heap {
        T val;
        std::unique_ptr<heap> l, r;

        heap(T v) : val(v), l(nullptr), r(nullptr) {}
    };

public:
    skew_heap() : root(nullptr), sz(0) {}

    void meld(skew_heap& sh) {
        sz += sh.size();
        root = meld(move(root), move(sh.root));
    }

    void push(T val) {
        root = meld(move(root), std::unique_ptr<heap>(new heap(val)));
        sz++;
    }

    T top() const {
        return root->val;
    }

    void pop() {
        assert(sz > 0);
        sz--;
        root = meld(move(root->r), move(root->l));
    }

    bool empty() const {
        return !root;
    }

    int size() const {
        return sz;
    }

private:
    std::unique_ptr<heap> meld(std::unique_ptr<heap> a, std::unique_ptr<heap> b) {
        if(!a) {
            return move(b);
        }
        if(!b) {
            return move(a);
        }
        if(!a && !b) {
            return nullptr;
        }
        if(a->val > b->val) {
            swap(a, b);
        }
        a->r = meld(move(a->r), move(b));
        swap(a->l, a->r);

        return move(a);
    }
private:
    std::unique_ptr<heap> root;
    int sz;
};


void dfs(vector<vector<int>> const& g, int v, vector<bool>& used, skew_heap<ll>& res, vector<int> const& a) {
    res.push(a[v]);
    used[v] = true;
    for(auto to : g[v]) {
        if(!used[to]) {
            dfs(g, to, used, res, a);
        }
    }
}

int main() {
    int N, M; cin >> N >> M;
    vector<int> a(N);
    for(int i = 0; i < N; ++i) {
        cin >> a[i];
        assert(a[i] != 0);
    }
    vector<vector<int>> g(N);
    for(int i = 0; i < M; ++i) {
        int x, y; cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    vector<bool> used(N);
    vector<skew_heap<ll>> hs;
    for(int i = 0; i < N; ++i) {
        if(!used[i]) {
            skew_heap<ll> hp;
            dfs(g, i, used, hp, a);
            if(hp.size() == 1) { // 
                ll t = hp.top(); hp.pop();
                hp.push(t + INF);
            }
            hs.push_back(move(hp));
        }
    }
    using P = pair<ll, int>;
    priority_queue<P, vector<P>, greater<P>> que;
    for(int i = 0; i < (int)hs.size(); ++i) {
        que.emplace(hs[i].top(), i);
    }

    ll ans = 0;
    int cnt = hs.size();
    while(cnt > 1) {
        if(que.size() < 2) {
            cout << "Impossible" << endl;
            return 0;
        }
        ll a1 = que.top().first, id1 = que.top().second; que.pop();
        if(a1 > INF) a1 -= INF;
        ll a2 = que.top().first, id2 = que.top().second; que.pop();
        if(a2 > INF) a2 -= INF;
        assert(id1 != id2);
        ans += a1 + a2;
        cnt--;
        hs[id1].pop(), hs[id2].pop();
        hs[id1].meld(hs[id2]);
        if(hs[id1].size() != 0) {
            que.emplace(hs[id1].top() + (hs[id1].size() == 1 ? INF : 0), id1);
        }
    }
    cout << ans << endl;
}