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.Generic;
using System.Linq;
using System.Text;
class Program{
	const int mod=1000000007;
	const long o=1;
	static void Main(){
		Sc sc=new Sc();
		int[] s=sc.Ia;
		int ans=0,m=0;
		int[] a=sc.Ia;
		Uf uf=new Uf(s[0]);
		for(int i=0;i<s[1];i++){
			int[] q=sc.Ia;
			uf.Union(q[0],q[1]);
		}
		int[] b=new int[s[0]];
		int[][] h=new int[uf.all+1][];
		int[] l=new int[uf.all+1];
		int[] rt=new int[uf.all+1];
		for(int i=0;i<s[0];i++){
			int q=uf.Root(i);
			if(b[q]==0){
				m++;
				b[q]=m;
				h[m]=new int[uf.Total(i)];
				rt[m]=q;
			}
			h[b[q]][l[b[q]]]=a[i];
			l[b[q]]++;
		}
		var pq=new Pq<Mo<int>>(m+1);
		for(int i=1;i<=m;i++){
			Array.Sort(h[i]);
			pq.Push(new Mo<int>(h[i][0],i));
			l[i]=1;
			h[i][0]=-1;
		}
		while(pq.cnt>1){
			int tn=pq.Top.n,td=pq.Top.d;
			pq.Pop();
			ans+=tn+pq.Top.n;
			uf.Union(rt[td],rt[pq.Top.d]);
			int nd=b[uf.Root(rt[td])];
			if(td==nd){td=pq.Top.d;}
			Array.Resize(ref h[nd],h[nd].Length+h[td].Length-1);
			Array.Copy(h[td],1,h[nd],h[nd].Length-h[td].Length+1,h[td].Length-1);
			Array.Sort(h[nd]);
			pq.Pop();
			if(l[nd]<h[nd].Length){
				pq.Push(new Mo<int>(h[nd][l[nd]],nd));
				h[nd][l[nd]]=-1;
				l[nd]++;
			}
		}
		Console.WriteLine("{0}",uf.all==1?ans.ToString():"Impossible");
	}
}
public class Mo<T>:IComparable{
	public int n;
	public T d;
	public Mo(int n,T d){this.n=n;this.d=d;}
	public int CompareTo(object obj){
		Mo<T> mymo=(Mo<T>)obj;
		if(mymo.n>n){return -1;}
		else if(mymo.n<n){return 1;}
		else{return 0;}
	}
}
public class Pq<T> where T:IComparable{
	private T[] he;
	public int cnt=0;
	public Pq(int max){he=new T[max];}
	public void Push(T x){
		int j=cnt;
		while(j!=0&&Compare(x,he[(j-1)/2])>0){he[j]=he[(j-1)/2];j=(j-1)/2;}
		he[j]=x;
		cnt++;
	}
	public void Pop(){
		cnt--;
		T r=he[cnt];
		int j=0;
		while(true){
			if(j*2+1<cnt){
				if(Compare(he[j*2+1],he[j*2+2])>0){j=j*2+1;}
				else{j=j*2+2;}
			}
			else if(j*2<cnt){j=j*2+1;}
			else{break;}
			if(Compare(he[j],r)<=0){j=(j-1)/2;break;}
			he[(j-1)/2]=he[j];
		}
		he[j]=r;
	}
	private int Compare(T x,T y){return y.CompareTo(x);}
	public T Top{get{return he[0];}}
}
public class Uf{
	private int[] arr,hi;
	public  int all;
	public Uf(int n){
		arr=new int[n];
		hi=new int[n];
		all=n;
		for(int i=0;i<n;i++){arr[i]=-1;}
	}
	public void Union(int a,int b){
		a=Root(a);
		b=Root(b);
		if(a!=b){
			if(hi[a]<hi[b]){
				int v=b;
				b=a;
				a=v;
			}
			arr[a]+=arr[b];
			hi[a]=Math.Max(hi[a],hi[b]+1);
			arr[b]=a;
			all--;
		}
	}
	public bool Same(int a,int b){return Root(a)==Root(b);}
	public int Total(int a){return -arr[Root(a)];}
	public int Root(int a){return arr[a]<0?a:arr[a]=Root(arr[a]);}
}

public class Sc{
	public int I{get{return int.Parse(Console.ReadLine());}}
	public long L{get{return long.Parse(Console.ReadLine());}}
	public double D{get{return double.Parse(Console.ReadLine());}}
	public string S{get{return Console.ReadLine();}}
	public int[] Ia{get{return Array.ConvertAll(Console.ReadLine().Split(),int.Parse);}}
	public long[] La{get{return Array.ConvertAll(Console.ReadLine().Split(),long.Parse);}}
	public double[] Da{get{return Array.ConvertAll(Console.ReadLine().Split(),double.Parse);}}
	public string[] Sa{get{return Console.ReadLine().Split();}}
}