;; -*- 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)

;;;
;;; 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
;;;

(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 nil)
         (comp-n (- n m))
         (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)))
    (when (= comp-n 1)
      (println 0)
      (return-from main))
    (dotimes (i n)
      (let ((root (ds-root dset i)))
        (pheap-push (aref as i) (aref comps root) #'<)))
    #>comps
    (dotimes (i n)
      (let ((comp (aref comps i)))
        (when (aref comps i)
          (let ((top (pheap-pop comp #'<)))
            (incf res top)
            (setf que (pheap-merge que comp #'<))))))
    #>res
    (dotimes (i (- n m 2))
      (unless que
        (write-line "Impossible")
        (return-from main))
      (incf res (pheap-pop que #'<)))
    (println res)))

#-swank (main)


Measured memory_bytes: 39908