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 Common Lisp (SBCL 1.1.14) (judge verdict: Wrong Answer)

;; -*- coding: utf-8 -*-
(eval-when (:compile-toplevel :load-toplevel :execute)
  (sb-int:defconstant-eqx OPT
    #+swank '(optimize (speed 3) (safety 2))
    #-swank '(optimize (speed 3) (safety 0) (debug 0))
    #'equal)
  #+swank (ql:quickload '(:cl-debug-print :fiveam) :silent t)
  #-swank (set-dispatch-macro-character
           #\# #\> (lambda (s c p) (declare (ignore c p)) (read s nil nil t))))
#+swank (cl-syntax:use-syntax cl-debug-print:debug-print-syntax)
#-swank (disable-debugger) ; for CS Academy

;; BEGIN_INSERTED_CONTENTS
(declaim (ftype (function * (values fixnum &optional)) read-fixnum))
(defun read-fixnum (&optional (in *standard-input*))
  (declare #.OPT)
  (macrolet ((%read-byte ()
               `(the (unsigned-byte 8)
                     #+swank (char-code (read-char in nil #\Nul))
                     #-swank (sb-impl::ansi-stream-read-byte in nil #.(char-code #\Nul) nil))))
    (let* ((minus nil)
           (result (loop (let ((byte (%read-byte)))
                           (cond ((<= 48 byte 57)
                                  (return (- byte 48)))
                                 ((zerop byte) ; #\Nul
                                  (error "Read EOF or #\Nul."))
                                 ((= byte #.(char-code #\-))
                                  (setf minus t)))))))
      (declare ((integer 0 #.most-positive-fixnum) result))
      (loop
        (let* ((byte (%read-byte)))
          (if (<= 48 byte 57)
              (setq result (+ (- byte 48)
                              (* 10 (the (integer 0 #.(floor most-positive-fixnum 10)) result))))
              (return (if minus (- result) result))))))))

;;;
;;; Disjoint set by Union-Find algorithm
;;;

(defstruct (disjoint-set
            (:constructor make-disjoint-set
                (size &aux (data (make-array size :element-type 'fixnum :initial-element -1))))
            (:conc-name ds-))
  (data nil :type (simple-array fixnum (*))))

(declaim (ftype (function * (values (mod #.array-total-size-limit) &optional)) ds-root))
(defun ds-root (disjoint-set x)
  "Returns the root of X."
  (declare (optimize (speed 3))
           ((mod #.array-total-size-limit) x))
  (let ((data (ds-data disjoint-set)))
    (if (< (aref data x) 0)
        x
        (setf (aref data x)
              (ds-root disjoint-set (aref data x))))))

(declaim (inline ds-unite!))
(defun ds-unite! (disjoint-set x1 x2)
  "Destructively unites X1 and X2 and returns true iff X1 and X2 become
connected for the first time."
  (let ((root1 (ds-root disjoint-set x1))
        (root2 (ds-root disjoint-set x2)))
    (unless (= root1 root2)
      (let ((data (ds-data disjoint-set)))
        ;; ensure the size of root1 >= the size of root2
        (when (> (aref data root1) (aref data root2))
          (rotatef root1 root2))
        (incf (aref data root1) (aref data root2))
        (setf (aref data root2) root1)))))

(declaim (inline ds-connected-p))
(defun ds-connected-p (disjoint-set x1 x2)
  "Returns true iff X1 and X2 have the same root."
  (= (ds-root disjoint-set x1) (ds-root disjoint-set x2)))

(declaim (inline ds-size))
(defun ds-size (disjoint-set x)
  "Returns the size of the connected component to which X belongs."
  (- (aref (ds-data disjoint-set)
           (ds-root disjoint-set x))))

(defmacro define-int-types (&rest bits)
  `(progn
     ,@(mapcar (lambda (b) `(deftype ,(intern (format nil "UINT~A" b)) () '(unsigned-byte ,b))) bits)
     ,@(mapcar (lambda (b) `(deftype ,(intern (format nil "INT~A" b)) () '(signed-byte ,b))) bits)))
(define-int-types 2 4 7 8 15 16 31 32 62 63 64)

;;;
;;; Binary heap
;;;

(define-condition heap-empty-error (simple-error)
  ((heap :initarg :heap :reader heap-empty-error-heap))
  (:report
   (lambda (condition stream)
     (format stream "Attempted to pop empty heap ~W" (heap-empty-error-heap condition)))))

(define-condition heap-full-error (simple-error)
  ((heap :initarg :heap :reader heap-full-error-heap)
   (item :initarg :item :reader heap-full-error-item))
  (:report
   (lambda (condition stream)
     (format stream "Attempted to push item ~W to full heap ~W"
             (heap-full-error-item condition)
             (heap-full-error-heap condition)))))

(defmacro define-binary-heap (name &key (order '#'>) (element-type 'fixnum))
  "Defines the binary heap specialized for the given order and the element
type. This macro defines a structure of the name NAME and relevant functions:
MAKE-<NAME>, <NAME>-PUSH, <NAME>-POP, <NAME>-REINITIALIZE, <NAME>-EMPTY-P,
<NAME>-COUNT, and <NAME>-PEEK."
  (check-type name symbol)
  (let* ((string-name (string name))
         (fname-push (intern (format nil "~A-PUSH" string-name)))
         (fname-pop (intern (format nil "~A-POP" string-name)))
         (fname-reinitialize (intern (format nil "~A-REINITIALIZE" string-name)))
         (fname-empty-p (intern (format nil "~A-EMPTY-P" string-name)))
         (fname-count (intern (format nil "~A-COUNT" string-name)))
         (fname-peek (intern (format nil "~A-PEEK" string-name)))
         (fname-make (intern (format nil "MAKE-~A" string-name)))
         (acc-position (intern (format nil "~A-POSITION" string-name)))
         (acc-data (intern (format nil "~A-DATA" string-name))))
    `(progn
       (defstruct (,name
                   (:constructor ,fname-make
                       (size
                        &aux (data ,(if (eql element-type '*)
                                        `(make-array (1+ size))
                                        `(make-array (1+ size) :element-type ',element-type))))))
         (data #() :type (simple-array ,element-type (*)) :read-only t)
         (position 1 :type (integer 1 #.most-positive-fixnum)))

       (declaim #+sbcl (sb-ext:maybe-inline ,fname-push))
       (defun ,fname-push (obj heap)
         "Adds OBJ to the end of HEAP."
         (declare (optimize (speed 3))
                  (type ,name heap))
         (symbol-macrolet ((position (,acc-position heap)))
           (let ((data (,acc-data heap)))
             (declare ((simple-array ,element-type (*)) data))
             (labels ((update (pos)
                        (declare (optimize (speed 3) (safety 0)))
                        (unless (= pos 1)
                          (let ((parent-pos (ash pos -1)))
                            (when (funcall ,order (aref data pos) (aref data parent-pos))
                              (rotatef (aref data pos) (aref data parent-pos))
                              (update parent-pos))))))
               (unless (< position (length data))
                 (error 'heap-full-error :heap heap :item obj))
               (setf (aref data position) obj)
               (update position)
               (incf position)
               heap))))

       (declaim #+sbcl (sb-ext:maybe-inline ,fname-pop))
       (defun ,fname-pop (heap)
         "Removes and returns the element at the top of HEAP."
         (declare (optimize (speed 3))
                  (type ,name heap))
         (symbol-macrolet ((position (,acc-position heap)))
           (let ((data (,acc-data heap)))
             (declare ((simple-array ,element-type (*)) data))
             (labels ((update (pos)
                        (declare (optimize (speed 3) (safety 0))
                                 ((integer 1 #.most-positive-fixnum) pos))
                        (let* ((child-pos1 (+ pos pos))
                               (child-pos2 (1+ child-pos1)))
                          (when (<= child-pos1 position)
                            (if (<= child-pos2 position)
                                (if (funcall ,order (aref data child-pos1) (aref data child-pos2))
                                    (unless (funcall ,order (aref data pos) (aref data child-pos1))
                                      (rotatef (aref data pos) (aref data child-pos1))
                                      (update child-pos1))
                                    (unless (funcall ,order (aref data pos) (aref data child-pos2))
                                      (rotatef (aref data pos) (aref data child-pos2))
                                      (update child-pos2)))
                                (unless (funcall ,order (aref data pos) (aref data child-pos1))
                                  (rotatef (aref data pos) (aref data child-pos1))))))))
               (when (= position 1)
                 (error 'heap-empty-error :heap heap))
               (prog1 (aref data 1)
                 (decf position)
                 (setf (aref data 1) (aref data position))
                 (update 1))))))

       (declaim (inline ,fname-reinitialize))
       (defun ,fname-reinitialize (heap)
         "Makes HEAP empty."
         (setf (,acc-position heap) 1)
         heap)

       (declaim (inline ,fname-empty-p))
       (defun ,fname-empty-p (heap)
         "Returns true iff HEAP is empty."
         (= 1 (,acc-position heap)))

       (declaim (inline ,fname-count))
       (defun ,fname-count (heap)
         "Returns the current number of the elements in HEAP."
         (- (,acc-position heap) 1))

       (declaim (inline ,fname-peek))
       (defun ,fname-peek (heap)
         "Returns the topmost element of HEAP."
         (if (= 1 (,acc-position heap))
             (error 'heap-empty-error :heap heap)
             (aref (,acc-data heap) 1))))))

;;;
;;; Meldable heap (pairing heap)
;;;
;;; Reference:
;;; https://topcoder.g.hatena.ne.jp/spaghetti_source/20120929/1348886107
;;;

;; Note: An empty heap is NIL.
;; TODO: handle the order of heap independently
(defstruct (pheap (:constructor %make-pheap (key))
                  (:conc-name %pheap-)
                  (:copier nil)
                  (:predicate nil))
  (key nil :type uint62)
  (next nil :type (or null pheap))
  (head nil :type (or null pheap)) ; head of children
  )

(declaim (inline pheap-merge))
(defun pheap-merge (node1 node2 order)
  (cond ((null node1) node2)
        ((null node2) node1)
        (t
         ;; ensure NODE1 < NODE2
         (when (funcall order (%pheap-key node2) (%pheap-key node1))
           (rotatef node1 node2))
         (setf (%pheap-next node2) (%pheap-head node1)
               (%pheap-head node1) node2)
         node1)))

(declaim (inline %pheap-merge-list1 %pheap-merge-list2 %pheap-merge-list3))

;; NOTE: Three implementations are available for MERGE-LIST, each of which has
;; good points and bad points.

;; Implementation 1, naive recursion
;; Pros: fastest on SBCL, no consing
;; Cons: there is a risk of stack exhaustion

(defun %pheap-merge-list1 (node order)
  (labels ((recur (node)
             (when node
               (let* ((a node)
                      (b (%pheap-next node)))
                 (if b
                     (let ((next (%pheap-next b)))
                       (setf (%pheap-next b) nil)
                       (let ((a+b (pheap-merge a b order)))
                         (pheap-merge a+b (recur next) order)))
                     a)))))
    (recur node)))

;; Implementation 2, manual stack by list
;; Pros: stack safe
;; Cons: most consing, 15% slower

(defun %pheap-merge-list2 (node order)
  (let (stack)
    (loop
      (unless node (return))
      (let ((a node)
            b)
        (setf node (%pheap-next node)
              (%pheap-next a) nil)
        (when node
          (setf b node
                node (%pheap-next node)
                (%pheap-next b) nil))
        (push (pheap-merge a b order) stack)))
    (dolist (part stack)
      (setf node (pheap-merge part node order)))
    node))

;; Implementation 3, manual stack by PHEAP
;; Pros: stack safe, no consing
;; Cons: a bit trickey, 5% slower

(defun %pheap-merge-list3 (node order)
  (let ((stack (load-time-value (sb-mop:class-prototype (find-class 'pheap)))))
    (setf (%pheap-next stack) nil)
    (loop
      (unless node (return))
      (let ((a node)
            b)
        (setf node (%pheap-next node)
              (%pheap-next a) nil)
        (when node
          (setf b node
                node (%pheap-next node)
                (%pheap-next b) nil))
        (setf a (pheap-merge a b order)
              (%pheap-next a) (%pheap-next stack)
              (%pheap-next stack) a)))
    (loop
      (unless (%pheap-next stack) (return))
      (let ((next (%pheap-next stack)))
        (setf (%pheap-next stack)
              (%pheap-next (%pheap-next stack)))
        (setf node (pheap-merge next node order))))
    node))

(declaim (inline pheep-peek))
(defun pheap-peek (node)
  (%pheap-key node))

;; Here we adopt clojure-like terms CONJ/DISJ as these are not operations to
;; make use of side effects, unlike PUSH/POP.
(declaim (inline pheap-conj))
(defun pheap-conj (node key order)
  (pheap-merge node (%make-pheap key) order))

(declaim (inline pheap-disj))
(defun pheap-disj (node order)
  (declare (pheap node))
  (%pheap-merge-list3 (%pheap-head node) order))

(defmacro pheap-push (key node order)
  `(setf ,node (pheap-conj ,node ,key ,order)))

(defmacro pheap-pop (node order)
  `(prog1 (pheap-peek ,node)
     (setf ,node (pheap-disj ,node ,order))))

(defmacro dbg (&rest forms)
  #+swank
  (if (= (length forms) 1)
      `(format *error-output* "~A => ~A~%" ',(car forms) ,(car forms))
      `(format *error-output* "~A => ~A~%" ',forms `(,,@forms)))
  #-swank (declare (ignore forms)))

(declaim (inline println))
(defun println (obj &optional (stream *standard-output*))
  (let ((*read-default-float-format* 'double-float))
    (prog1 (princ obj stream) (terpri stream))))

(defconstant +mod+ 1000000007)

;;;
;;; Body
;;;

(define-binary-heap heap
  :order (lambda (p1 p2)
           (< (the uint62 (pheap-peek p1))
              (the uint62 (pheap-peek p2))))
  :element-type pheap)

(defun main ()
  (let* ((n (read))
         (m (read))
         (as (make-array n :element-type 'uint32))
         (comps (make-array n :element-type '(or null pheap) :initial-element nil))
         (dset (make-disjoint-set n))
         (que (make-heap n))
         (res 0))
    (declare (uint32 n m)
             (uint62 res))
    (dotimes (i n)
      (setf (aref as i) (read-fixnum)))
    (dotimes (i m)
      (let ((x (read-fixnum))
            (y (read-fixnum)))
        (ds-unite! dset x y)))
    (dotimes (i n)
      (let ((root (ds-root dset i)))
        (pheap-push (aref as i) (aref comps root) #'<)))
    (dotimes (i n)
      (when (aref comps i)
        (heap-push (aref comps i) que)))
    (loop
      (let* ((comp1 (heap-pop que))
             (a1 (pheap-pop comp1 #'<)))
        (when (heap-empty-p que)
          (println res)
          (return-from main))
        (let* ((comp2 (heap-pop que))
               (a2 (pheap-pop comp2 #'<)))
          (incf res (+ a1 a2))
          (let ((new-comp (pheap-merge comp1 comp2 #'<)))
            (when (and (null new-comp)
                       (not (heap-empty-p que)))
              (write-line "Impossible")
              (return-from main))
            (heap-push new-comp que)))))))

#-swank (main)