import scala.collection.mutable
object Main extends App {
  import scala.io.StdIn._

  val Array(n, m) = readLine.trim.split(' ').map(_.toInt)
  val values = Array.fill(n){readInt()}
  val edges = Array.fill(m){
    readLine.trim.split(' ').map(_.toInt - 1) match {
      case Array(s, t) ⇒ (s, t)
      case _ ⇒ ???
    }
  }

  val toEdge = Array.fill(n){Nil: List[Int]}
  val parent = Array.fill(n){-1}
  val depth = Array.fill(n){0}
  for ((s, t) ← edges) {
    toEdge(s) ::= t
    toEdge(t) ::= s
  }
  for (i ← 0 until n if parent(i) == -1) {
    val queue = mutable.Queue[Int](i)
    while (queue.nonEmpty) {
      val top = queue.dequeue()
      for (next ← toEdge(top) if parent(top) != next && parent(next) == -1) {
        parent(next) = top
        depth(next) = depth(top) + 1
        queue.enqueue(next)
      }
    }
  }
  val uft = new UnionFind(n)
  val root = (0 until n).toArray
  for ((s, t) ← edges if parent(s) != t && parent(t) != s && !uft.isSame(s, t)) {
    var sr = root(uft.find(s))
    var tr = root(uft.find(t))
    while (sr != tr) {
      if (depth(sr) < depth(tr)) {
        val newRoot = root(uft.find(parent(tr)))
        uft.unite(tr, newRoot)
        values(newRoot) += values(tr)
        val newP = uft.find(newRoot)
        root(newP) = newRoot
        tr = newRoot
      }else {
        val newRoot = root(uft.find(parent(sr)))
        uft.unite(sr, newRoot)
        values(newRoot) += values(sr)
        val newP = uft.find(newRoot)
        root(newP) = newRoot
        sr = newRoot
      }
    }
  }
  val newEdges = edges.collect{
    case (s, t) if !uft.isSame(s, t) ⇒ (root(uft.find(s)), root(uft.find(t)))
  }
  val newToEdge = Array.fill(n){Nil: List[Int]}
  val newParent = Array.fill(n){-1}
  val newChildCount = Array.fill(n){0}
  for ((s, t) ← newEdges) {
    newToEdge(s) ::= t
    newToEdge(t) ::= s
  }
  for (i ← 0 until n if root(uft.find(i)) == i && newParent(i) == -1) {
    val queue = mutable.Queue(i)
    while(queue.nonEmpty) {
      val top = queue.dequeue()
      for (next ← newToEdge(top) if newParent(top) != next) {
        newParent(next) = top
        newChildCount(top) += 1
        queue.enqueue(next)
      }
    }
  }
  val queue = mutable.Queue[Int]()
  for (i ← 0 until n if root(uft.find(i)) == i && newChildCount(i) == 0) queue.enqueue(i)
  val maxToLeaf = Array.fill(n){0}
  val maxInSubTree = Array.fill(n){0}
  while(queue.nonEmpty) {
    val top = queue.dequeue()
    maxToLeaf(top) += values(top)
    maxInSubTree(top) += values(top)
    if (newParent(top) != -1) {
      maxInSubTree(newParent(top)) = math.max(maxInSubTree(newParent(top)), maxToLeaf(newParent(top)) + maxToLeaf(top))
      maxToLeaf(newParent(top)) = math.max(maxToLeaf(newParent(top)), maxToLeaf(top))
      newChildCount(newParent(top)) -= 1
      if (newChildCount(newParent(top)) == 0) queue.enqueue(newParent(top))
    }
  }
  println(
    maxInSubTree.max
  )
}
class UnionFind(val size:Int) {
  private val array = Array.fill(size){-1}
  def find(a: Int): Int = {
    if (array(a) < 0) {
      a
    }else {
      array(a) = find(array(a))
      array(a)
    }
  }
  def isSame(a: Int, b: Int): Boolean = find(a) == find(b)
  def unite(a: Int, b: Int): Unit = {
    val ar = find(a)
    val br = find(b)
    if (ar != br){
      if (array(ar) < array(br)){
        array(ar) += array(br)
        array(br) = ar
      }else {
        array(br) += array(ar)
        array(ar) = br
      }
    }
  }
}


Measured memory_bytes: 227392