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# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	public void Solve(){
		
		var UF = new UnionFind(N);
		for(int i=0;i<M;i++){
			UF.Unite(X[i], Y[i]);
		}
		
		if(UF.MemCnt(0) == N){
			Console.WriteLine(0);
			return;
		}
		
		SkewHeap<Pair>[] L = new SkewHeap<Pair>[N];
		for(int i=0;i<N;i++) L[i] = new SkewHeap<Pair>();
		for(int i=0;i<N;i++){
			L[UF.Parent(i)].Push(new Pair(i,A[i]));
		}
		
		long tot = 0;
		var SH = new SkewHeap<Pair>();
		
		for(int i=0;i<N;i++){
			if(UF.IsRoot(i)){
				var p = L[i].Top; L[i].Pop();
				SH.Push(p);
			}
		}
		while(SH.Count > 0){
//Console.WriteLine(SH.Count);
			if(UF.MemCnt(0) == N){
				Console.WriteLine(tot);
				return;
			}
			
			var a = SH.Top; SH.Pop();
			if(SH.Count == 0) break;
			var b = SH.Top; SH.Pop();
			
			tot += a.Cost + b.Cost;
//Console.WriteLine("{0} {1}:tot:{2}",a,b,tot);
			UF.Unite(a.Pos, b.Pos);
			var np = UF.Parent(a.Pos);
			
			var sa = L[UF.Parent(a.Pos)];
			var sb = L[UF.Parent(b.Pos)];
//Console.WriteLine("sa:");sa.Dump();
//Console.WriteLine("sb:");sb.Dump();
			
			// sa.Merge(sb);
			// L[np] = sa;
			
			if(sa.Count > sb.Count){
				while(sb.Count > 0){
					sa.Push(sb.Top); sb.Pop();
				}
				L[np] = sa;
			} else {
				while(sa.Count > 0){
					sb.Push(sa.Top); sa.Pop();
				}
				L[np] = sb;
			}
			
			
//Console.WriteLine("L[np]:");L[np].Dump();
			
			if(L[np].Count > 0){
				SH.Push(L[np].Top); L[np].Pop();
			}
			
		}
		
		if(UF.MemCnt(0) != N){
			Console.WriteLine("Impossible");
		} else {
			Console.WriteLine(tot);
		}
		
		
	}
	int N,M;
	long[] A;
	int[] X,Y;
	public Sol(){
		var d = ria();
		N = d[0]; M = d[1];
		A = rla();
		X = new int[M];
		Y = new int[M];
		for(int i=0;i<M;i++){
			d = ria();
			X[i] = d[0]; Y[i] = d[1];
		}
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}


class UnionFind{
	
	int[] parent;
	int[] mem;
	int compo;
	int N;
	
	public UnionFind(UnionFind v){
		// copy constructor
		N = v.N;
		parent = new int[N];
		mem = new int[N];
		for(int i=0;i<N;i++){
			parent[i] = v.parent[i];
			mem[i] = v.mem[i];
		}
		compo = v.compo;
	}
	public UnionFind(int n_){
		Initialize(n_);
	}
	
	public void Initialize(int n_){
		N = n_;
		parent = new int[N];
		mem=new int[N];
		for(int i=0;i<N;i++){
			parent[i] = i;
			mem[i] = 1;
		}
		compo = N;
	}
	
	public int Parent(int a){
		if(parent[a] == a)return a;
		return parent[a] = Parent(parent[a]);
	}
	
	public bool IsUnited(int a,int b){
		return Parent(a) == Parent(b);
	}
	
	public void Unite(int a,int b){
		a = Parent(a); b = Parent(b);//Parent()を呼ぶことでa以上のノードは全てparentがrootになる
		if(a == b)return;
		parent[a] = b;
		mem[b] += mem[a];
		compo -= 1;
	}
	
	public bool IsRoot(int x){
		return x == parent[x];
	}
	public int MemCnt(int x){
		return mem[Parent(x)];
	}
	
	public void Dump(){
		for(int i=0;i<parent.Length;i++){
			Console.Write(i == 0 ? "{0}" : " {0}",parent[i]);
		}
		Console.WriteLine("");
	}
	
	public int Compo{
		get{
			return compo;
		}
	}
	
}


class Pair : IComparable<Pair> {
	public int Pos;
	public long Cost;
	public Pair(int p, long c) {
		Pos = p; Cost = c;
	}
	public int CompareTo(Pair t) {
		//return this.Cost > t.Cost ? -1 : this.Cost < t.Cost ? 1 : 0;
		return this.Cost > t.Cost ? 1 : this.Cost < t.Cost ? -1 : 0;
	}
	public override String ToString(){
		return String.Format("[{0} {1}]",Pos,Cost);
	}
}


class SkewHeap<T> where T:IComparable<T>{
	public int Count{
		get{return cnt;}
		private set{cnt=value;}
	}
	
	public SkewHeap(){
		root=null;
		this.Count=0;
	}
	
	public void Push(T v){
		NodeSH<T> p=new NodeSH<T>(v);
		root=NodeSH<T>.Meld(root,p);
		this.Count++;
	}
	
	public void Merge(SkewHeap<T> t){
		var cnt0 = this.Count + t.Count;
		root = NodeSH<T>.Meld(root, t.root);
		Count = cnt0;
	}
	
	
	public void Pop(){
		if(root==null)return;
		root=NodeSH<T>.Meld(root.L,root.R);
		this.Count--;
	}
	
	public T Top{
		get{return root.Val;}
	}
	
	public void Dump(){
		if(Count == 0){
			Console.WriteLine("empty");
			return;
		}
		var Q = new Queue<NodeSH<T>>();
		Q.Enqueue(root);
		List<NodeSH<T>> L = new List<NodeSH<T>>();
		while(Q.Count > 0){
			var nd = Q.Dequeue();
			L.Add(nd);
			if(nd.L != null) Q.Enqueue(nd.L);
			if(nd.R != null) Q.Enqueue(nd.R);
		}
		Console.WriteLine(String.Join(" ",L.Select(nd => nd.Val)));
	}
	
	
	int cnt;
	NodeSH<T> root;
	
	class NodeSH<S> where S : IComparable<S> {
		public NodeSH<S> L, R;
		public S Val;

		public NodeSH(S v){
			Val = v;
			L = null; R = null;
		}
		public static NodeSH<S> Meld(NodeSH<S> a, NodeSH<S> b){
			if(a == null)return b;
			if (b == null) return a;
			if (a.Val.CompareTo(b.Val) > 0) swap(ref a, ref b);
			a.R = Meld(a.R, b);
			swap(ref a.L, ref a.R);
			return a;
		}

		static void swap<U>(ref U x, ref U y) {
			U t = x; x = y; y = t;
		}
	}
}