import Data.Array.IO
import qualified Data.ByteString.Char8 as BS
import Data.Maybe
import Control.Monad
import Control.Applicative

type UnionFindIO = IOArray Int (Int,Int)

newUFIO :: Int -> IO UnionFindIO
newUFIO n = newListArray (1,n) (zip [1..n] (repeat 1))
 
findUFIO :: UnionFindIO -> Int -> IO Int
findUFIO uf x = do
  (parent,size) <- readArray uf x
  if parent == x then
    return x
    else do
    next <- findUFIO uf parent
    writeArray uf x (next,size)
    return next
 
sameUFIO :: UnionFindIO -> Int -> Int -> IO Bool
sameUFIO uf x y = do
  xx <- findUFIO uf x
  yy <- findUFIO uf y
  return $ xx == yy
 
uniteUFIO :: UnionFindIO -> Int -> Int -> IO ()
uniteUFIO uf x y = do
  xx <- findUFIO uf x
  yy <- findUFIO uf y
  (_,xs) <- readArray uf xx
  (_,ys) <- readArray uf yy

  if xx == yy then
    return ()
    else if xs < ys then do
    writeArray uf xx (yy,0)
    else if xs > ys then do
    writeArray uf yy (xx,0)
    else do
    writeArray uf yy (xx,0)
    writeArray uf xx (xx,xs+1)

listToTuple2 [a,b] = (a,b)
modifyArray arr i f = readArray arr i >>= \x -> writeArray arr i (f x)
readIntBS = fst . fromJust . BS.readInt

main = do
  (n,m) <- listToTuple2 . map readIntBS . BS.words <$> BS.getLine :: IO (Int,Int)
  ps <- map readIntBS . BS.words <$> BS.getLine :: IO [Int]
  uf <- newUFIO n

  arr <- newArray (1,n) 0 :: IO (IOArray Int Int)
  forM_ (zip [1..] ps) $ \(i,p) -> do
    writeArray arr p i
  
  
  replicateM m $ do
    (x,y) <- listToTuple2 . map readIntBS . BS.words <$> BS.getLine :: IO (Int,Int)
    uniteUFIO uf x y

  c <- forM [1..n] $ \i -> do
    j <- readArray arr i
    isSame <- sameUFIO uf i j
    return $ if isSame then 1 else 0

  print $ sum c
