#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<utility>
#include<set>
#include<stack>
#include<list>
#include<deque>
#include<bitset>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<climits>
#include<cmath>
#include<cctype>

#define pb push_back
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ren(i,a,b) for(int i=a;i>=b;i--)
#define ff first
#define ss second
#define pll pair<long long int,long long int>
#define pii pair<int,int>
#define vll vector<long long int>
#define vii vector<int>
#define gi(n) scanf("%d",&n)
#define gll(n) scanf("%lld",&n)
#define gstr(n) scanf("%s",n)
#define gl(n) cin >> n
#define oi(n) printf("%d",n)
#define oll(n) printf("%lld",n)
#define ostr(n) printf("%s",n)
#define ol(n) cout << n
#define os cout<<" "
#define on cout<<"\n"
#define o2(a,b) cout<<a<<" "<<b
#define all(n) n.begin(),n.end()
#define present(s,x) (s.find(x) != s.end())
#define cpresent(s,x) (find(all(s),x) != s.end())
using namespace std;

typedef unsigned long long int ull;
typedef long long int ll;
int main()
{ios_base::sync_with_stdio(false);
ll n;string s;ll m=1e9+7,idx=0,f=0,f1=0,ans=0;
gl(n);
cin>>s;
rep(i,1,n-1)
{
    if(s[i]!=s[0])
    {
        f1=1;break;
    }
}
if(f1==0)
{
     ans=(n*n)%m;
    ans=(ans*n)%m;
    ol(ans);
    return 0;
}
if(s[0]!=s[n-1])
{
idx=0;
f=1;
}
if(f==0)
{
    rep(i,1,n-1)
    {
        if(s[i]!=s[i-1])
        {
            idx=i;
            break;
        }
    }
}
int j=idx;ll c=1;
do
{
    if(s[j]==s[(j-1+n)%n])
    {
        c++;
    }
    else
    {
        //ol(c);on;
        ans=(ans+(((c*c)%m)*n)%m)%m;
        //ol(ans);on;
        c=1;
    }
    j=(j+1)%n;
}while(idx!=j);
ol(ans%m);
return 0;
}


#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<utility>
#include<set>
#include<stack>
#include<list>
#include<deque>
#include<bitset>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<climits>
#include<cmath>
#include<cctype>

#define pb push_back
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ren(i,a,b) for(int i=a;i>=b;i--)
#define ff first
#define ss second
#define pll pair<long long int,long long int>
#define pii pair<int,int>
#define vll vector<long long int>
#define vii vector<int>
#define gi(n) scanf("%d",&n)
#define gll(n) scanf("%lld",&n)
#define gstr(n) scanf("%s",n)
#define gl(n) cin >> n
#define oi(n) printf("%d",n)
#define oll(n) printf("%lld",n)
#define ostr(n) printf("%s",n)
#define ol(n) cout << n
#define os cout<<" "
#define on cout<<"\n"
#define o2(a,b) cout<<a<<" "<<b
#define all(n) n.begin(),n.end()
#define present(s,x) (s.find(x) != s.end())
#define cpresent(s,x) (find(all(s),x) != s.end())
using namespace std;

typedef unsigned long long int ull;
typedef long long int ll;
ll m=1e9+7;

ll p(ll a,ll b)
{
    ll r=1;
    while(b>0)
    {
        if(b&1)
        r=(r*a)%m;
        a=(a*a)%m;
        b/=2;
    }
    return r;
}
int main()
{ios_base::sync_with_stdio(false);
int n;ll c[4]={0};
gl(n);
string s;cin>>s;
rep(i,0,n-1)
{
    if(s[i]=='A')c[0]++;
    else if(s[i]=='G')c[1]++;
    else if(s[i]=='C')c[2]++;
    else c[3]++;
}
sort(c,c+4);
ll ans;
rep(i,0,3)
if(c[i]==c[3])ans++;
ol(p(ans,n));
return 0;
}


#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<utility>
#include<set>
#include<stack>
#include<list>
#include<deque>
#include<bitset>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<climits>
#include<cmath>
#include<cctype>

#define pb push_back
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ren(i,a,b) for(int i=a;i>=b;i--)
#define ff first
#define ss second
#define pll pair<long long int,long long int>
#define pii pair<int,int>
#define vll vector<long long int>
#define vii vector<int>
#define gi(n) scanf("%d",&n)
#define gll(n) scanf("%lld",&n)
#define gstr(n) scanf("%s",n)
#define gl(n) cin >> n
#define oi(n) printf("%d",n)
#define oll(n) printf("%lld",n)
#define ostr(n) printf("%s",n)
#define ol(n) cout << n
#define os cout<<" "
#define on cout<<"\n"
#define o2(a,b) cout<<a<<" "<<b
#define all(n) n.begin(),n.end()
#define present(s,x) (s.find(x) != s.end())
#define cpresent(s,x) (find(all(s),x) != s.end())
using namespace std;

typedef unsigned long long int ull;
typedef long long int ll;
int main()
{ios_base::sync_with_stdio(false);
ll n;string s;ll m=1e9+7,idx=0,f=0,f1=0,ans=0;
gl(n);set<char> a;
cin>>s;
rep(i,1,n-1)
{
    if(s[i]!=s[0])
    {
        f1=1;break;
    }
}
if(f1==0||n==1)
{
     //ans=(n*n)%m;
    //ans=(ans*n)%m;
    ol("1");
    return 0;
}
rep(i,0,n-1)
{
    a.insert(s[i]);
}
/*if(s[0]!=s[n-1])
{
idx=0;
f=1;
}
if(f==0)
{
    rep(i,1,n-1)
    {
        if(s[i]!=s[i-1])
        {
            idx=i;
            break;
        }
    }
}
int j=idx;ll c=1;
do
{
    if(s[j]==s[(j-1+n)%n])
    {
        c++;
    }
    else
    {
        //ol(c);on;
        ans=(ans+(((c*c)%m)*n)%m)%m;
        //ol(ans);on;
        c=1;
    }
    j=(j+1)%n;
}while(idx!=j);
ol(ans%m);*/
ll k;
if(a.size()==2)
{
    k=1;
}
else
k=n;
rep(i,0,n-1)
{
    if(s[i]!=s[(i-1+n)%n]&&s[i]!=s[(i+1)%n])
    {

        ans=(ans+((a.size()-1)*k)%m)%m;
        //ol(ans);on;
        //ol(s[i]);on;
    }
}
ol((ans+n)%m);on;
return 0;
}


#include <iostream>

int cnt[256];
const long long modulo = 1e9 + 7;

long long pw(long long x, int N)
{
	if (N == 0)
		return 1;
	if (N == 1)
		return x;

	long long res = pw(x, N >> 1);
	res *= res;
	x %= modulo;

	if(x & 1)
		res = ( res * x ) % modulo;

	return res;
}

int main()
{
	int N;
	std::cin >> N;

	for (int i = 0; i < N; ++i)
	{
		char ch;
		std::cin >> ch;
		cnt[ch]++;
	}

	int mx = cnt['A'], mxCnt = 1;

	for(int i = 'B'; i <= 'T'; ++i)
	{
		if(mx < cnt[i])
		{
			mx = cnt[i];
			mxCnt = 1;
		}
		else if(mx == cnt[i])
		{
			mxCnt ++;
		}
	}

	std::cout << pw(mxCnt, N) << std::endl;
}


#include <iostream>

int cnt[256];
const long long modulo = 1e9 + 7;

long long pw(long long x, int N)
{
	if (N == 0)
		return 1;
	if (N == 1)
		return x;

	long long res = pw(x, N >> 1);
	res *= res;
	res %= modulo;

	if(N & 1)
		res = ( res * x ) % modulo;

	return res;
}

int main()
{
	int N;
	std::cin >> N;

	for (int i = 0; i < N; ++i)
	{
		char ch;
		std::cin >> ch;
		cnt[ch]++;
	}

	int mx = cnt['A'], mxCnt = 1;

	for(int i = 'B'; i <= 'T'; ++i)
	{
		if(mx < cnt[i])
		{
			mx = cnt[i];
			mxCnt = 1;
		}
		else if(mx == cnt[i])
		{
			mxCnt ++;
		}
	}

	std::cout << pw(mxCnt, N) << std::endl;
}


#include <iostream>

int cnt[256];
const long long modulo = 1e9 + 7;

long long pw(long long x, int N)
{
	if (N == 0)
		return 1;
	if (N == 1)
		return x;

	long long res = pw(x, N >> 1);
	res *= res;
	res %= modulo;

	if(x & 1)
		res = ( res * x ) % modulo;

	return res;
}

int main()
{
	int N;
	std::cin >> N;

	for (int i = 0; i < N; ++i)
	{
		char ch;
		std::cin >> ch;
		cnt[ch]++;
	}

	int mx = cnt['A'], mxCnt = 1;

	for(int i = 'B'; i <= 'T'; ++i)
	{
		if(mx < cnt[i])
		{
			mx = cnt[i];
			mxCnt = 1;
		}
		else if(mx == cnt[i])
		{
			mxCnt ++;
		}
	}

	std::cout << pw(mxCnt, N) << std::endl;
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

class Program
{
    private static bool[] visited;
    private static List<List<int>> components;
    private static List<int>[] neighbours;
    static void Main(string[] args)
    {
        components = new List<List<int>>();

        var inp = Console.ReadLine().Split().Select(int.Parse).ToArray();
        var result = 0;
        int n = inp[0];
        int m = inp[1];
        int k = inp[2];
        visited = new bool[200005];
        neighbours = new List<int>[200005];
        var colors = Console.ReadLine().Split().Select(int.Parse).ToArray();
        for (int i = 0; i < m; i++)
        {
            inp = Console.ReadLine().Split().Select(x => int.Parse(x)-1).ToArray();
            int a = inp[0];
            int b = inp[1];
            if (neighbours[a] == null)
                neighbours[a] = new List<int>(n);
            if (neighbours[b] == null)
                neighbours[b] = new List<int>(n);
            neighbours[a].Add(b);
            neighbours[b].Add(a);
        }
        for (int i = 0; i < n; i++)
        {
            if (!visited[i])
            {
                components.Add(new List<int>(n));
                DFS(i);
            }
        }
        int[] colorsInComp = new int[k + 1];
        foreach (var comp in components)
        {
            var max = 0;
            colorsInComp = new int[k+1];
            foreach (var el in comp)
            {
                colorsInComp[colors[el]]++;
                if (colorsInComp[colors[el]] > max)
                    max = colorsInComp[colors[el]];
            }
            result += comp.Count - max;
        }
        Console.WriteLine(result);
    }

    static void DFS(int x)
    {
        components.Last().Add(x);
        visited[x] = true;
        if (neighbours[x] == null)
            return;
        foreach (var nei in neighbours[x])
            if (!visited[nei])
                DFS(nei);
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

class Program
{
    private static bool[] visited;
    private static List<List<int>> components;
    private static List<int>[] neighbours;
    static void Main(string[] args)
    {
        components = new List<List<int>>();

        var inp = Console.ReadLine().Split().Select(int.Parse).ToArray();
        var result = 0;
        int n = inp[0];
        int m = inp[1];
        int k = inp[2];
        visited = new bool[200005];
        neighbours = new List<int>[200005];
        var colors = Console.ReadLine().Split().Select(int.Parse).ToArray();
        for (int i = 0; i < m; i++)
        {
            inp = Console.ReadLine().Split().Select(x => int.Parse(x)-1).ToArray();
            int a = inp[0];
            int b = inp[1];
            if (neighbours[a] == null)
                neighbours[a] = new List<int>();
            if (neighbours[b] == null)
                neighbours[b] = new List<int>();
            neighbours[a].Add(b);
            neighbours[b].Add(a);
        }
        for (int i = 0; i < n; i++)
        {
            if (!visited[i])
            {
                components.Add(new List<int>(200));
                DFS(i);
            }
        }
        int[] colorsInComp = new int[k + 1];
        foreach (var comp in components)
        {
            var max = 0;
            colorsInComp = new int[k+1];
            foreach (var el in comp)
            {
                colorsInComp[colors[el]]++;
                if (colorsInComp[colors[el]] > max)
                    max = colorsInComp[colors[el]];
            }
            result += comp.Count - max;
        }
        Console.WriteLine(result);
    }

    static void DFS(int x)
    {
        components.Last().Add(x);
        visited[x] = true;
        if (neighbours[x] == null)
            return;
        foreach (var nei in neighbours[x])
            if (!visited[nei])
                DFS(nei);
    }
}


import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.io.PrintWriter
import java.lang.StringBuilder
import java.math.BigInteger
import java.util.*

class UnionFind(n: Int) {
    private val rank = IntArray(n) { 0 }
    private val parent = IntArray(n) { -1 }

    fun find(x: Int): Int {
        if (parent[x] < 0) {
            return x
        }
        parent[x] = find(parent[x])
        return parent[x]
    }

    fun unite(x: Int, y: Int) {
        val x1 = find(x)
        val y1 = find(y)
        if (x1 == y1) {
            return
        }
        if (rank[x1] < rank[y1]) {
            parent[y1] += parent[x1]
            parent[x1] = y1
        } else {
            parent[x1] += parent[y1]
            parent[y1] = x1
            if (rank[x1] == rank[y1]) {
                rank[x1]++
            }
        }
    }

    fun same(x: Int, y: Int): Boolean {
        return find(x) == find(y)
    }

    fun size(x: Int): Int {
        return -parent[find(x)]
    }
}

fun PrintWriter.solve(sc: FastScanner) {
    val n = sc.nextInt()
    val m = sc.nextInt()
    val k = sc.nextInt()
    val c = Array(n) { sc.nextInt() }
    val uf = UnionFind(n)
    for (i in 0 until m) {
        val l = sc.nextInt()
        val r = sc.nextInt()
        uf.unite(l - 1, r - 1)
    }
    var map = mutableMapOf<Int, MutableMap<Int, Int>>()
    for (i in 0 until n) {
        val p = uf.find(i)
        if (!map.containsKey(p)) {
            map[p] = mutableMapOf()
        }
        map[p]?.set(c[i], (map[p]?.get(c[i]) ?: 0) + 1)
    }
    var ans = 0
    for (color in map.values) {
        ans += color.values.sum() - color.values.max()!!
    }
    println(ans)
}

fun main(args: Array<String>) {
    val writer = PrintWriter(System.out, false)
    writer.solve(FastScanner(System.`in`))
    writer.flush()
}

class FastScanner(s: InputStream) {
    private var st = StringTokenizer("")
    private val br = BufferedReader(InputStreamReader(s))

    fun next(): String {
        while (!st.hasMoreTokens()) st = StringTokenizer(br.readLine())

        return st.nextToken()
    }

    fun nextInt() = next().toInt()
    fun nextLong() = next().toLong()
    fun nextLine() = br.readLine()
    fun nextDouble() = next().toDouble()
    fun ready() = br.ready()
}


import java.io.*
import java.util.*

fun DataReader.solve(out: PrintWriter) {
    val n = nextInt()
    val m = nextInt()
    nextInt()

    val a = Array(n) { mutableListOf<Int>() }

    val c = readIntArray(n)
    for (i in 1..m) {
        val u = nextInt() - 1
        val v = nextInt() - 1

        a[u].add(v)
        a[v].add(u)
    }

    val componentId = IntArray(n) { -1 }
    var nextId = 0

    fun dfs(u: Int) {
        if (componentId[u] != -1) return
        componentId[u] = nextId

        return a[u].forEach(::dfs)
    }

    var result = 0

    for (i in 0 until n) {
        if (componentId[i] != -1) continue
        dfs(i)
        val currentCmp = componentId.indices.filter { componentId[it] == nextId }
        val max = currentCmp.groupBy { c[it] }.entries.map { it.value.size }.max()!!

        result += currentCmp.size - max

        nextId++
    }

    out.println(result)
}

fun Boolean.toYesNo() = if (this) "Yes" else "No"

class DataReader(private val reader: BufferedReader) {
    var st : StringTokenizer? = null
    companion object {
        fun createFromFile(name: String) = DataReader(BufferedReader(FileReader(name)))
    }

    fun next() : String? {
        while (st == null || !st!!.hasMoreTokens()) {
            val s = reader.readLine() ?: return null
            st = StringTokenizer(s)
        }

        return st?.nextToken()
    }

    fun nextToken() = next()!!

    fun nextInt() = nextToken().toInt()
    fun nextLong() = nextToken().toLong()
    fun readIntArray(n: Int) : IntArray {
        val result = IntArray(n)
        result.indices.forEach { i -> result[i] = nextInt() }
        return result
    }

    fun nextLine() = reader.readLine()
}

fun main(args: Array<String>) {
    val r: Reader
    val out: PrintWriter
    if (System.getProperty("ONLINE_JUDGE") == null) {
        r = FileReader("input.txt")
        out = PrintWriter("output.txt")
    } else {
        r = InputStreamReader(System.`in`)
        out = PrintWriter(System.out)
    }

    DataReader(BufferedReader(r)).solve(out)
    out.flush()
}


import java.io.*
import java.util.*

fun DataReader.solve(out: PrintWriter) {
    val n = nextInt()
    val m = nextInt()
    nextInt()

    val a = Array(n) { mutableListOf<Int>() }

    val c = readIntArray(n)
    for (i in 1..m) {
        val u = nextInt() - 1
        val v = nextInt() - 1

        a[u].add(v)
        a[v].add(u)
    }

    val componentId = IntArray(n) { -1 }

    val q = Array(n) { mutableListOf<Int>() }

    var nextId = 0

    fun dfs(u: Int) {
        if (componentId[u] != -1) return
        componentId[u] = nextId
        q[nextId].add(u)

        return a[u].forEach(::dfs)
    }

    var result = 0

    for (i in 0 until n) {
        if (componentId[i] != -1) continue
        dfs(i)
        val currentCmp = q[nextId]
        val max = currentCmp.groupBy { c[it] }.entries.map { it.value.size }.max()!!

        result += currentCmp.size - max

        nextId++
    }

    out.println(result)
}

fun Boolean.toYesNo() = if (this) "Yes" else "No"

class DataReader(private val reader: BufferedReader) {
    var st : StringTokenizer? = null
    companion object {
        fun createFromFile(name: String) = DataReader(BufferedReader(FileReader(name)))
    }

    fun next() : String? {
        while (st == null || !st!!.hasMoreTokens()) {
            val s = reader.readLine() ?: return null
            st = StringTokenizer(s)
        }

        return st?.nextToken()
    }

    fun nextToken() = next()!!

    fun nextInt() = nextToken().toInt()
    fun nextLong() = nextToken().toLong()
    fun readIntArray(n: Int) : IntArray {
        val result = IntArray(n)
        result.indices.forEach { i -> result[i] = nextInt() }
        return result
    }

    fun nextLine() = reader.readLine()
}

fun main(args: Array<String>) {
    val r: Reader
    val out: PrintWriter
    if (System.getProperty("ONLINE_JUDGE") == null) {
        r = FileReader("input.txt")
        out = PrintWriter("output.txt")
    } else {
        r = InputStreamReader(System.`in`)
        out = PrintWriter(System.out)
    }

    DataReader(BufferedReader(r)).solve(out)
    out.flush()
}


#ifdef ONLINE_JUDGE
    #define NDEBUG 1
#endif
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>

#define long int64_t
#define fore(i,k,n) for (int _k = (k), _n = (n), i = _k; i <= _n; ++i)
#define forr(i,n,k) for (int _k = (k), _n = (n), i = _n; i >= _k; --i)
#define LIST_INIT_CAP 4
#define HASH_INIT_CAP 1024
#define HASH_SKIP 11
#define TREE_INIT_CAP 1024
#define TREE_MAX_HEIGHT 64
#define DEQUE_INIT_CAP 1024
#define HEAP_INIT_CAP 1024
#define TAKEN 1
#define EMPTY 0
#define TOMB -1

typedef struct list {
    int32_t* data;
    unsigned    size;
    unsigned    capacity;
} l_i;

static const l_i l_zero_i = { 0 };

void l_free_i(l_i* list) {
    free(list->data);
    *list = l_zero_i;
}

void l_resize_i(l_i* list) {
    if (list->capacity < LIST_INIT_CAP) list->capacity = LIST_INIT_CAP;
    else list->capacity <<= 2;
    list->data = (int32_t*)realloc(list->data, sizeof(int32_t) * list->capacity);
    assert(list->data != NULL);
}

bool l_empty_i(l_i* list) {
    return (list->size == 0);
}

void l_add_i(l_i* list, int32_t value) {
    if (list->size == list->capacity) l_resize_i(list);
    list->data[list->size] = value;
    ++list->size;
}

void l_insertAt_i(l_i* list, unsigned idx, int32_t val) {
    assert(idx < list->size);
    if (list->size == list->capacity) l_resize_i(list);
    for (int i = list->size; i > idx; --i) {
        list->data[i] = list->data[i - 1];
    }
    list->data[idx] = val;
    ++list->size;
}

void l_removeAt_i(l_i* list, unsigned idx) {
    assert(idx < list->size);
    for (int i = idx; i < list->size - 1; ++i) {
        list->data[i] = list->data[i + 1];
    }
    --list->size;
}

inline void l_swap_i(l_i* list, unsigned i, unsigned j) {
    assert(i < list->size);
    assert(j < list->size);
    int32_t tmp = list->data[i];
    list->data[i] = list->data[j];
    list->data[j] = tmp;
}

l_i graph[200001];
int colors[200001];
bool visited[200001];

int dfs(int node) {
    if (visited[node]) return 0;
    visited[node] = true;
    int res = 1;
    fore (i, 0, graph[node].size - 1) {
        res += dfs(graph[node].data[i]);
    }
    return res;
}

int main() {
    int n, m, k;
    scanf("%d %d %d", &n, &m, &k);
    fore (i, 1, n) {
        scanf("%d", &colors[i]);
    }
    fore (i, 1, m) {
        int a, b;
        scanf("%d %d", &a, &b);
        int ca = colors[a];
        int cb = colors[b];
        if (ca != cb) {
            l_add_i(&graph[ca], cb);
            l_add_i(&graph[cb], ca);
        }
    }
    int answer = 0;
    fore (i, 1, 200000) {
        if (graph[i].size && !visited[i]) answer += dfs(i) - 1;
    }
    printf("%d\n", answer);
    return 0;
}


#ifdef ONLINE_JUDGE
    #define NDEBUG 1
#endif
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>

#define long int64_t
#define fore(i,k,n) for (int _k = (k), _n = (n), i = _k; i <= _n; ++i)
#define forr(i,n,k) for (int _k = (k), _n = (n), i = _n; i >= _k; --i)
#define LIST_INIT_CAP 4
#define HASH_INIT_CAP 64
#define HASH_SKIP 11
#define TREE_INIT_CAP 1024
#define TREE_MAX_HEIGHT 64
#define DEQUE_INIT_CAP 1024
#define HEAP_INIT_CAP 1024
#define TAKEN 1
#define EMPTY 0
#define TOMB -1

#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
typedef struct list {
    int32_t* data;
    unsigned    size;
    unsigned    capacity;
} l_i;

static const l_i l_zero_i = { 0 };

void l_free_i(l_i* list) {
    free(list->data);
    *list = l_zero_i;
}

void l_resize_i(l_i* list) {
    if (list->capacity < LIST_INIT_CAP) list->capacity = LIST_INIT_CAP;
    else list->capacity <<= 2;
    list->data = (int32_t*)realloc(list->data, sizeof(int32_t) * list->capacity);
    assert(list->data != NULL);
}

bool l_empty_i(l_i* list) {
    return (list->size == 0);
}

void l_add_i(l_i* list, int32_t value) {
    if (list->size == list->capacity) l_resize_i(list);
    list->data[list->size] = value;
    ++list->size;
}

void l_insertAt_i(l_i* list, unsigned idx, int32_t val) {
    assert(idx < list->size);
    if (list->size == list->capacity) l_resize_i(list);
    for (int i = list->size; i > idx; --i) {
        list->data[i] = list->data[i - 1];
    }
    list->data[idx] = val;
    ++list->size;
}

void l_removeAt_i(l_i* list, unsigned idx) {
    assert(idx < list->size);
    for (int i = idx; i < list->size - 1; ++i) {
        list->data[i] = list->data[i + 1];
    }
    --list->size;
}

inline void l_swap_i(l_i* list, unsigned i, unsigned j) {
    assert(i < list->size);
    assert(j < list->size);
    int32_t tmp = list->data[i];
    list->data[i] = list->data[j];
    list->data[j] = tmp;
}

unsigned hashcode_ui(uint32_t key) {
    key = (key+0x7ed55d16) + (key<<12);
    key = (key^0xc761c23c) ^ (key>>19);
    key = (key+0x165667b1) + (key<<5);
    key = (key+0xd3a2646c) ^ (key<<9);
    key = (key+0xfd7046c5) + (key<<3);
    key = (key^0xb55a4f09) ^ (key>>16);
    return key;
}
unsigned hashcode_i(int32_t ikey) {
    return hashcode_ui((uint32_t)ikey);
}
int32_t cmp_i(int32_t a, int32_t b) {
    return a - b;
}
typedef struct hentry_i_i {
    int       mark;
    int32_t key;
    int32_t val;
} hentry_i_i;

typedef struct h_i_i {
    hentry_i_i*   data;
    unsigned            size;
    unsigned            capacity;
    unsigned            iter;
} h_i_i;

static const h_i_i h_zero_i_i = { 0 };

h_i_i h_alloc_i_i(unsigned cap) {
    h_i_i hash = { 0 };
    hash.capacity = HASH_INIT_CAP;
    while ((cap << 1) > hash.capacity) {
       hash.capacity <<= 2;
    }
    hash.data = (hentry_i_i*)calloc(sizeof(hentry_i_i), hash.capacity);
    assert(hash.data != NULL);
    return hash;
}

void h_free_i_i(h_i_i* hash) {
    free(hash->data);
    *hash = h_zero_i_i;
}

void h_clear_i_i(h_i_i* hash) {
    if (hash->capacity != HASH_INIT_CAP) {
        hash->capacity = HASH_INIT_CAP;
        hash->data = (hentry_i_i*)realloc(hash->data,
                sizeof(hentry_i_i) * hash->capacity);
        assert(hash->data != NULL);
    }
    memset(hash->data, 0, sizeof(hentry_i_i) * hash->capacity);
    hash->size = 0;
    hash->iter = 0;
}

bool h_put_i_i(h_i_i* hash, int32_t key, int32_t val);

void h_resize_i_i(h_i_i* hash) {
    hentry_i_i* olddata = hash->data;
    unsigned oldcap = hash->capacity;
    hash->size = 0;
    hash->capacity <<= 2;
    hash->data = (hentry_i_i*)calloc(sizeof(hentry_i_i), hash->capacity);
    assert(hash->data != NULL);
    for (unsigned i = 0; i < oldcap; ++i) {
        if (olddata[i].mark == TAKEN) {
            h_put_i_i(hash, olddata[i].key, olddata[i].val);
        }
    }
    free(olddata);
}

bool h_find_i_i(h_i_i* hash, int32_t key, unsigned* pidx) {
    assert(hash->data != NULL);
    *pidx = UINT_MAX;
    bool foundTomb = false;
    unsigned capminusone = hash->capacity - 1;
    unsigned idx = hashcode_i(key) & capminusone;
    while (hash->data[idx].mark != EMPTY) {
        if (hash->data[idx].mark == TOMB && !foundTomb) {
            foundTomb = true;
            *pidx = idx;
            idx = (idx + HASH_SKIP) & capminusone;
        }
        else if (hash->data[idx].mark == TAKEN &&
                cmp_i(key, hash->data[idx].key) == 0) {
            *pidx = idx;
            return true;
        } else {
            idx = (idx + HASH_SKIP) & capminusone;
        }
    }
    if (*pidx == UINT_MAX) *pidx = idx;
    return false;
}

bool h_get_i_i(h_i_i* hash, int32_t key, int32_t* val) {
    unsigned idx;
    if (h_find_i_i(hash, key, &idx)) {
        if (val) *val = hash->data[idx].val;
        return true;
    } else {
        return false;
    }
}

bool h_put_i_i(h_i_i* hash, int32_t key, int32_t val) {
    unsigned idx;
    bool found = h_find_i_i(hash, key, &idx);
    hash->data[idx].mark = TAKEN;
    hash->data[idx].key = key;
    hash->data[idx].val = val;
    if (!found && ++hash->size > (hash->capacity >> 1)) h_resize_i_i(hash);
    return found;
}

bool h_remove_i_i(h_i_i* hash, int32_t key) {
    unsigned idx;
    if (h_find_i_i(hash, key, &idx)) {
        hash->data[idx].mark = TOMB;
        --hash->size;
        return true;
    } else {
        return false;
    }
}

void h_iterReset_i_i(h_i_i* hash) {
    hash->iter = 0;
}

bool h_iterNext_i_i(h_i_i* hash, int32_t* key, int32_t* val) {
    while (hash->iter < hash->capacity) {
        if (hash->data[hash->iter].mark == TAKEN) {
            *key = hash->data[hash->iter].key;
            *val = hash->data[hash->iter].val;
            ++hash->iter;
            return true;
        }
        ++hash->iter;
    }
    return false;
}

int colors[200001];
bool visited[200001];
l_i graph[200001];
h_i_i hashc;

int dfs(int node) {
    if (visited[node]) return 0;
    visited[node] = true;
    int color = colors[node];
    int numcol = 0;
    h_get_i_i(&hashc, color, &numcol);
    h_put_i_i(&hashc, color, numcol + 1);
    int res = 1;
    fore (i, 0, graph[node].size - 1) {
        res += dfs(graph[node].data[i]);
    }
    return res;
}

int main() {
    int n, m, k;
    scanf("%d %d %d", &n, &m, &k);
    fore (i, 1, n) {
        scanf("%d", &colors[i]);
    }
    int answer = 0;
    fore (i, 1, m) {
        int a, b;
        scanf("%d %d", &a, &b);
        l_add_i(&graph[a], b);
        l_add_i(&graph[b], a);
    }
    hashc = h_alloc_i_i(0);
    fore (i, 1, n) {
        int gsz = 0;
        if (graph[i].size && !visited[i]) {
            gsz = dfs(i);
            int key, val, maxc = -1;
            h_iterReset_i_i(&hashc);
            while (h_iterNext_i_i(&hashc, &key, &val)) {
                    maxc = max(maxc, val);
            }
            h_clear_i_i(&hashc);
            answer += gsz - maxc;
        }
    }
    printf("%d\n", answer);
    return 0;
}


#ifdef ONLINE_JUDGE
    #define NDEBUG 1
#endif
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>

#define long int64_t
#define fore(i,k,n) for (int _k = (k), _n = (n), i = _k; i <= _n; ++i)
#define forr(i,n,k) for (int _k = (k), _n = (n), i = _n; i >= _k; --i)
#define LIST_INIT_CAP 4
#define HASH_INIT_CAP 64
#define HASH_SKIP 11
#define TREE_INIT_CAP 1024
#define TREE_MAX_HEIGHT 64
#define DEQUE_INIT_CAP 1024
#define HEAP_INIT_CAP 1024
#define TAKEN 1
#define EMPTY 0
#define TOMB -1

#define max(a,b) (((a)>(b))?(a):(b))
typedef struct list {
    int32_t* data;
    unsigned    size;
    unsigned    capacity;
} l_i;

static const l_i l_zero_i = { 0 };

void l_free_i(l_i* list) {
    free(list->data);
    *list = l_zero_i;
}

void l_resize_i(l_i* list) {
    if (list->capacity < LIST_INIT_CAP) list->capacity = LIST_INIT_CAP;
    else list->capacity <<= 2;
    list->data = (int32_t*)realloc(list->data, sizeof(int32_t) * list->capacity);
    assert(list->data != NULL);
}

bool l_empty_i(l_i* list) {
    return (list->size == 0);
}

void l_add_i(l_i* list, int32_t value) {
    if (list->size == list->capacity) l_resize_i(list);
    list->data[list->size] = value;
    ++list->size;
}

void l_insertAt_i(l_i* list, unsigned idx, int32_t val) {
    assert(idx < list->size);
    if (list->size == list->capacity) l_resize_i(list);
    for (int i = list->size; i > idx; --i) {
        list->data[i] = list->data[i - 1];
    }
    list->data[idx] = val;
    ++list->size;
}

void l_removeAt_i(l_i* list, unsigned idx) {
    assert(idx < list->size);
    for (int i = idx; i < list->size - 1; ++i) {
        list->data[i] = list->data[i + 1];
    }
    --list->size;
}

inline void l_swap_i(l_i* list, unsigned i, unsigned j) {
    assert(i < list->size);
    assert(j < list->size);
    int32_t tmp = list->data[i];
    list->data[i] = list->data[j];
    list->data[j] = tmp;
}

unsigned hashcode_ui(uint32_t key) {
    key = (key+0x7ed55d16) + (key<<12);
    key = (key^0xc761c23c) ^ (key>>19);
    key = (key+0x165667b1) + (key<<5);
    key = (key+0xd3a2646c) ^ (key<<9);
    key = (key+0xfd7046c5) + (key<<3);
    key = (key^0xb55a4f09) ^ (key>>16);
    return key;
}
unsigned hashcode_i(int32_t ikey) {
    return hashcode_ui((uint32_t)ikey);
}
int32_t cmp_i(int32_t a, int32_t b) {
    return a - b;
}
typedef struct hentry_i_i {
    int       mark;
    int32_t key;
    int32_t val;
} hentry_i_i;

typedef struct h_i_i {
    hentry_i_i*   data;
    unsigned            size;
    unsigned            capacity;
    unsigned            iter;
} h_i_i;

static const h_i_i h_zero_i_i = { 0 };

h_i_i h_alloc_i_i(unsigned cap) {
    h_i_i hash = { 0 };
    hash.capacity = HASH_INIT_CAP;
    while ((cap << 1) > hash.capacity) {
       hash.capacity <<= 2;
    }
    hash.data = (hentry_i_i*)calloc(sizeof(hentry_i_i), hash.capacity);
    assert(hash.data != NULL);
    return hash;
}

void h_free_i_i(h_i_i* hash) {
    free(hash->data);
    *hash = h_zero_i_i;
}

void h_clear_i_i(h_i_i* hash) {
    free(hash->data);
    *hash = h_alloc_i_i(0);
}

bool h_put_i_i(h_i_i* hash, int32_t key, int32_t val);

void h_resize_i_i(h_i_i* hash) {
    hentry_i_i* olddata = hash->data;
    unsigned oldcap = hash->capacity;
    hash->size = 0;
    hash->capacity <<= 2;
    hash->data = (hentry_i_i*)calloc(sizeof(hentry_i_i), hash->capacity);
    assert(hash->data != NULL);
    for (unsigned i = 0; i < oldcap; ++i) {
        if (olddata[i].mark == TAKEN) {
            h_put_i_i(hash, olddata[i].key, olddata[i].val);
        }
    }
    free(olddata);
}

bool h_find_i_i(h_i_i* hash, int32_t key, unsigned* pidx) {
    assert(hash->data != NULL);
    *pidx = UINT_MAX;
    bool foundTomb = false;
    unsigned capminusone = hash->capacity - 1;
    unsigned idx = hashcode_i(key) & capminusone;
    while (hash->data[idx].mark != EMPTY) {
        if (hash->data[idx].mark == TOMB && !foundTomb) {
            foundTomb = true;
            *pidx = idx;
            idx = (idx + HASH_SKIP) & capminusone;
        }
        else if (hash->data[idx].mark == TAKEN &&
                cmp_i(key, hash->data[idx].key) == 0) {
            *pidx = idx;
            return true;
        } else {
            idx = (idx + HASH_SKIP) & capminusone;
        }
    }
    if (*pidx == UINT_MAX) *pidx = idx;
    return false;
}

bool h_get_i_i(h_i_i* hash, int32_t key, int32_t* val) {
    unsigned idx;
    if (h_find_i_i(hash, key, &idx)) {
        if (val) *val = hash->data[idx].val;
        return true;
    } else {
        return false;
    }
}

bool h_put_i_i(h_i_i* hash, int32_t key, int32_t val) {
    unsigned idx;
    bool found = h_find_i_i(hash, key, &idx);
    hash->data[idx].mark = TAKEN;
    hash->data[idx].key = key;
    hash->data[idx].val = val;
    if (!found && ++hash->size > (hash->capacity >> 1)) h_resize_i_i(hash);
    return found;
}

bool h_remove_i_i(h_i_i* hash, int32_t key) {
    unsigned idx;
    if (h_find_i_i(hash, key, &idx)) {
        hash->data[idx].mark = TOMB;
        --hash->size;
        return true;
    } else {
        return false;
    }
}

void h_iterReset_i_i(h_i_i* hash) {
    hash->iter = 0;
}

bool h_iterNext_i_i(h_i_i* hash, int32_t* key, int32_t* val) {
    while (hash->iter < hash->capacity) {
        if (hash->data[hash->iter].mark == TAKEN) {
            *key = hash->data[hash->iter].key;
            *val = hash->data[hash->iter].val;
            ++hash->iter;
            return true;
        }
        ++hash->iter;
    }
    return false;
}

int colors[200001];
bool visited[200001];
l_i graph[200001];
h_i_i hashc;

int dfs(int node) {
    if (visited[node]) return 0;
    visited[node] = true;
    int color = colors[node];
    int numcol = 0;
    h_get_i_i(&hashc, color, &numcol);
    h_put_i_i(&hashc, color, numcol + 1);
    int res = 1;
    fore (i, 0, graph[node].size - 1) {
        res += dfs(graph[node].data[i]);
    }
    return res;
}

int main() {
    int n, m, k;
    scanf("%d %d %d", &n, &m, &k);
    fore (i, 1, n) {
        scanf("%d", &colors[i]);
    }
    int answer = 0;
    fore (i, 1, m) {
        int a, b;
        scanf("%d %d", &a, &b);
        l_add_i(&graph[a], b);
        l_add_i(&graph[b], a);
    }
    hashc = h_alloc_i_i(0);
    fore (i, 1, n) {
        int gsz = 0;
        if (graph[i].size && !visited[i]) {
            gsz = dfs(i);
            int key, val, maxc = -1;
            h_iterReset_i_i(&hashc);
            while (h_iterNext_i_i(&hashc, &key, &val)) {
                    maxc = max(maxc, val);
            }
            h_clear_i_i(&hashc);
            answer += gsz - maxc;
        }
    }
    printf("%d\n", answer);
    return 0;
}


#ifdef ONLINE_JUDGE
    #define NDEBUG 1
#endif
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>

#define long int64_t
#define fore(i,k,n) for (int _k = (k), _n = (n), i = _k; i <= _n; ++i)
#define forr(i,n,k) for (int _k = (k), _n = (n), i = _n; i >= _k; --i)
#define LIST_INIT_CAP 4
#define HASH_INIT_CAP 64
#define HASH_SKIP 11
#define TREE_INIT_CAP 1024
#define TREE_MAX_HEIGHT 64
#define DEQUE_INIT_CAP 1024
#define HEAP_INIT_CAP 1024
#define TAKEN 1
#define EMPTY 0
#define TOMB -1

#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
typedef struct list {
    int32_t* data;
    unsigned    size;
    unsigned    capacity;
} l_i;

static const l_i l_zero_i = { 0 };

void l_free_i(l_i* list) {
    free(list->data);
    *list = l_zero_i;
}

void l_resize_i(l_i* list) {
    if (list->capacity < LIST_INIT_CAP) list->capacity = LIST_INIT_CAP;
    else list->capacity <<= 2;
    list->data = (int32_t*)realloc(list->data, sizeof(int32_t) * list->capacity);
    assert(list->data != NULL);
}

bool l_empty_i(l_i* list) {
    return (list->size == 0);
}

void l_add_i(l_i* list, int32_t value) {
    if (list->size == list->capacity) l_resize_i(list);
    list->data[list->size] = value;
    ++list->size;
}

void l_insertAt_i(l_i* list, unsigned idx, int32_t val) {
    assert(idx < list->size);
    if (list->size == list->capacity) l_resize_i(list);
    for (int i = list->size; i > idx; --i) {
        list->data[i] = list->data[i - 1];
    }
    list->data[idx] = val;
    ++list->size;
}

void l_removeAt_i(l_i* list, unsigned idx) {
    assert(idx < list->size);
    for (int i = idx; i < list->size - 1; ++i) {
        list->data[i] = list->data[i + 1];
    }
    --list->size;
}

inline void l_swap_i(l_i* list, unsigned i, unsigned j) {
    assert(i < list->size);
    assert(j < list->size);
    int32_t tmp = list->data[i];
    list->data[i] = list->data[j];
    list->data[j] = tmp;
}

unsigned hashcode_ui(uint32_t key) {
    key = (key+0x7ed55d16) + (key<<12);
    key = (key^0xc761c23c) ^ (key>>19);
    key = (key+0x165667b1) + (key<<5);
    key = (key+0xd3a2646c) ^ (key<<9);
    key = (key+0xfd7046c5) + (key<<3);
    key = (key^0xb55a4f09) ^ (key>>16);
    return key;
}
unsigned hashcode_i(int32_t ikey) {
    return hashcode_ui((uint32_t)ikey);
}
int32_t cmp_i(int32_t a, int32_t b) {
    return a - b;
}
typedef struct hentry_i_i {
    int       mark;
    int32_t key;
    int32_t val;
} hentry_i_i;

typedef struct h_i_i {
    hentry_i_i*   data;
    unsigned            size;
    unsigned            capacity;
    unsigned            iter;
} h_i_i;

static const h_i_i h_zero_i_i = { 0 };

h_i_i h_alloc_i_i(unsigned cap) {
    h_i_i hash = { 0 };
    hash.capacity = HASH_INIT_CAP;
    while ((cap << 1) > hash.capacity) {
       hash.capacity <<= 2;
    }
    hash.data = (hentry_i_i*)calloc(sizeof(hentry_i_i), hash.capacity);
    assert(hash.data != NULL);
    return hash;
}

void h_free_i_i(h_i_i* hash) {
    free(hash->data);
    *hash = h_zero_i_i;
}

void h_clear_i_i(h_i_i* hash) {
    if (hash->capacity != HASH_INIT_CAP) {
        hash->capacity = HASH_INIT_CAP;
        hash->data = (hentry_i_i*)realloc(hash->data,
                sizeof(hentry_i_i) * hash->capacity);
        assert(hash->data != NULL);
    }
    memset(hash->data, 0, sizeof(hentry_i_i) * hash->capacity);
    hash->size = 0;
    hash->iter = 0;
}

bool h_put_i_i(h_i_i* hash, int32_t key, int32_t val);

void h_resize_i_i(h_i_i* hash) {
    hentry_i_i* olddata = hash->data;
    unsigned oldcap = hash->capacity;
    hash->size = 0;
    hash->capacity <<= 2;
    hash->data = (hentry_i_i*)calloc(sizeof(hentry_i_i), hash->capacity);
    assert(hash->data != NULL);
    for (unsigned i = 0; i < oldcap; ++i) {
        if (olddata[i].mark == TAKEN) {
            h_put_i_i(hash, olddata[i].key, olddata[i].val);
        }
    }
    free(olddata);
}

bool h_find_i_i(h_i_i* hash, int32_t key, unsigned* pidx) {
    assert(hash->data != NULL);
    *pidx = UINT_MAX;
    bool foundTomb = false;
    unsigned capminusone = hash->capacity - 1;
    unsigned idx = hashcode_i(key) & capminusone;
    while (hash->data[idx].mark != EMPTY) {
        if (hash->data[idx].mark == TOMB && !foundTomb) {
            foundTomb = true;
            *pidx = idx;
            idx = (idx + HASH_SKIP) & capminusone;
        }
        else if (hash->data[idx].mark == TAKEN &&
                cmp_i(key, hash->data[idx].key) == 0) {
            *pidx = idx;
            return true;
        } else {
            idx = (idx + HASH_SKIP) & capminusone;
        }
    }
    if (*pidx == UINT_MAX) *pidx = idx;
    return false;
}

bool h_get_i_i(h_i_i* hash, int32_t key, int32_t* val) {
    unsigned idx;
    if (h_find_i_i(hash, key, &idx)) {
        if (val) *val = hash->data[idx].val;
        return true;
    } else {
        return false;
    }
}

bool h_put_i_i(h_i_i* hash, int32_t key, int32_t val) {
    unsigned idx;
    bool found = h_find_i_i(hash, key, &idx);
    hash->data[idx].mark = TAKEN;
    hash->data[idx].key = key;
    hash->data[idx].val = val;
    if (!found && ++hash->size > (hash->capacity >> 1)) h_resize_i_i(hash);
    return found;
}

bool h_remove_i_i(h_i_i* hash, int32_t key) {
    unsigned idx;
    if (h_find_i_i(hash, key, &idx)) {
        hash->data[idx].mark = TOMB;
        --hash->size;
        return true;
    } else {
        return false;
    }
}

void h_iterReset_i_i(h_i_i* hash) {
    hash->iter = 0;
}

bool h_iterNext_i_i(h_i_i* hash, int32_t* key, int32_t* val) {
    while (hash->iter < hash->capacity) {
        if (hash->data[hash->iter].mark == TAKEN) {
            *key = hash->data[hash->iter].key;
            *val = hash->data[hash->iter].val;
            ++hash->iter;
            return true;
        }
        ++hash->iter;
    }
    return false;
}

int colors[200001];
bool visited[200001];
l_i graph[200001];
h_i_i hashc;

int dfs(int node) {
    if (visited[node]) return 0;
    visited[node] = true;
    int color = colors[node];
    int numcol = 0;
    h_get_i_i(&hashc, color, &numcol);
    h_put_i_i(&hashc, color, numcol + 1);
    int res = 1;
    fore (i, 0, graph[node].size - 1) {
        res += dfs(graph[node].data[i]);
    }
    return res;
}

int main() {
    int n, m, k;
    scanf("%d %d %d", &n, &m, &k);
    fore (i, 1, n) {
        scanf("%d", &colors[i]);
    }
    int answer = 0;
    fore (i, 1, m) {
        int a, b;
        scanf("%d %d", &a, &b);
        l_add_i(&graph[min(a, b)], max(a, b));
    }
    hashc = h_alloc_i_i(0);
    fore (i, 1, n) {
        int gsz = 0;
        if (graph[i].size && !visited[i]) {
            gsz = dfs(i);
            int key, val, maxc = -1;
            h_iterReset_i_i(&hashc);
            while (h_iterNext_i_i(&hashc, &key, &val)) {
                    maxc = max(maxc, val);
            }
            h_clear_i_i(&hashc);
            answer += gsz - maxc;
        }
    }
    printf("%d\n", answer);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N	200000

int dsu[N];

int find(int x) {
	return dsu[x] < 0 ? x : (dsu[x] = find(dsu[x]));
}

void join(int x, int y) {
	x = find(x);
	y = find(y);

	if (x == y)
		return;
	if (dsu[x] < dsu[y])
		dsu[y] = x;
	else if (dsu[y] < dsu[x])
		dsu[x] = y;
	else {
		dsu[x]--;
		dsu[y] = x;
	}
}

struct item {
	int group, color;
} ii[N];

int count(int i, int j) {
	int k, max = 0, cnt = 1;

	for (k = i + 1; k <= j; k++) {
		if (max < cnt)
			max = cnt;
		if (k == j || ii[k - 1].color != ii[k].color)
			cnt = 1;
		else
			cnt++;
	}
	return max;
}

int compare(const void *a, const void *b) {
	struct item *pa = (struct item *) a;
	struct item *pb = (struct item *) b;

	return pa->group != pb->group ? pa->group - pb->group
		: pa->color - pb->color;
}

int main() {
	int i, j, n, m, k, cnt;
	static int cc[N];

	scanf("%d%d%d", &n, &m, &k);
	for (i = 0; i < n; i++)
		scanf("%d", &cc[i]);
	for (i = 0; i < n; i++)
		dsu[i] = -1;
	while (m-- > 0) {
		int l, r;

		scanf("%d%d", &l, &r);
		l--, r--;
		join(l, r);
	}
	for (i = 0; i < n; i++)
		find(i);
	for (i = 0; i < n; i++) {
		ii[i].group = dsu[i] < 0 ? i : dsu[i];
		ii[i].color = cc[i];
	}
	qsort(ii, n, sizeof(*ii), compare);
	cnt = n;
	for (i = 0, j = 1; j <= n; j++)
		if (j == n || ii[j - 1].group != ii[j].group) {
			cnt -= count(i, j);
			i = j;
		}
	printf("%d\n", cnt);
	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N	200000
#define K	200000

int dsu[N];

int find(int x) {
	return dsu[x] < 0 ? x : (dsu[x] = find(dsu[x]));
}

void join(int x, int y) {
	x = find(x);
	y = find(y);

	if (x == y)
		return;
	if (dsu[x] < dsu[y])
		dsu[y] = x;
	else if (dsu[y] < dsu[x])
		dsu[x] = y;
	else {
		dsu[x]--;
		dsu[y] = x;
	}
}

struct item {
	int i, group, color;
} ii[N];

int compare(const void *a, const void *b) {
	struct item *pa = (struct item *) a;
	struct item *pb = (struct item *) b;

	return pa->group != pb->group ? pa->group - pb->group
		: (pa->color != pb->color ? pa->color - pb->color : pa->i - pb->i);
}

int main() {
	int i, n, m, k, changecnt;
	static int cc[N];

	scanf("%d%d%d", &n, &m, &k);
	for (i = 0; i < n; i++)
		scanf("%d", &cc[i]);
	for (i = 0; i < n; i++)
		dsu[i] = -1;
	while (m-- > 0) {
		int l, r;

		scanf("%d%d", &l, &r);
		l--, r--;
		join(l, r);
	}
	for (i = 0; i < n; i++) {
		ii[i].i = i;
		ii[i].group = find(i);
		ii[i].color = cc[i];
	}
	qsort(ii, n, sizeof(*ii), compare);
	i = 0;
	changecnt = 0;
	while (i < n) {
		int j = i, k, cmax, max, cnt;

		while (j < n && ii[j].group == ii[i].group)
			j++;
		max = cnt = 0;
		for (k = i; k < j; k++) {
			if (k == i || ii[k].color == ii[k - 1].color)
				cnt++;
			else
				cnt = 1;
			if (max < cnt) {
				max = cnt;
				cmax = ii[k].color;
			}
		}
		for (k = i; k < j; k++)
			if (ii[k].color != cmax)
				changecnt++;
		i = j;
	}
	printf("%d\n", changecnt);
	return 0;
}


//misc
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>

uint64_t hash_shift64(uint64_t key) {
	key = (~key) + (key << 21); // key = (key << 21) - key - 1;
	key = key ^ (key >> 24);
	key = (key + (key << 3)) + (key << 8); // key * 265
	key = key ^ (key >> 14);
	key = (key + (key << 2)) + (key << 4); // key * 21
	key = key ^ (key >> 28);
	key = key + (key << 31);
	return key;
}

#define KT uint64_t
#define VT int
#define EQ(a,b) ((a)==(b))
#define HASH_N 99991
#define HASH_F hash_shift64

typedef struct HashItem {
	KT key;
	VT value;
	size_t hash;
	struct HashItem *next;
} HashItem;

typedef struct OpenHash {
	int n;
	HashItem *a[HASH_N];
} OpenHash;

void OpenHash_init(OpenHash *self) {
	self->n = 0;
	memset(self->a, 0, sizeof(self->a));
}

int OpenHash_put(OpenHash *self, KT key, VT value) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			p->value = value;
			return 0;
		}
		p = p->next;
	}
	HashItem *x = malloc(sizeof(HashItem));
	x->key = key;
	x->value = value;
	x->hash = hash;
	x->next = self->a[idx];
	self->a[idx] = x;
	self->n ++;
	return 1;
}

VT *OpenHash_get(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			return &p->value;
		}
		p = p->next;
	}
	return NULL;
}

int OpenHash_del(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx], *prev=NULL;
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			if (prev==NULL) self->a[idx] = p->next;
			else prev->next = p->next;
			//NOTE: free p->key and p->value
			free(p);
			self->n--;
			return 1;
		}
		prev = p;
		p = p->next;
	}
	return 0;
}

void OpenHash_clear(OpenHash *self) {
	for(size_t i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		while (p) {
			HashItem *q = p->next;
			//NOTE: free p->key or p->value
			free(p);
			p = q;
		}
		self->a[i] = NULL;
	}
	self->n = 0;
}

void OpenHash_print(OpenHash *self, char *fmt) {
	printf("%d %d\n", self->n, HASH_N);
	for(int i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		if (p==NULL) continue;
		printf("%d", i);
		while(p) {
			printf(" %lu ", p->hash);
			printf(fmt, p->key, p->value);
			p = p->next;
		}
		printf("\n");
	}
}

//-----------------------------------------------------

int dsu_init(int *g, int n) {
	for(int i=0; i<n; i++) g[i] = i;
}

int dsu_find(int *g, int x) {
	int p=x, f;
	while(g[p] != p) p=g[p];
	while(g[x] != p) f=g[x], g[x]=p, x=f;
	return p;
}

void dsu_union(int *g, int x, int y) {
	g[dsu_find(g, y)] = dsu_find(g, x);
}

//-----------------------------------------------------

#define N 200000
int c[N];
int g[N];
int max[N];
int cnt[N];
OpenHash oh;

int main() {
	int n, m, k;
	OpenHash *h = &oh;
	while(scanf("%d %d %d", &n, &m, &k)==3) {
		OpenHash_init(h);
		dsu_init(g, n);
		for(int i=0; i<n; i++) {
			scanf("%d", &c[i]);
			c[i]--;
		}
		for(int i=0; i<m; i++) {
			int x,y;
			scanf("%d %d", &x, &y);
			dsu_union(g, x-1, y-1);
		}
		for(int i=0; i<n; i++) {
			int r = dsu_find(g, i);
			int key = r*k+c[i]; //(r,c[i])
			int *pv = OpenHash_get(h, key);
			if (pv==NULL) OpenHash_put(h, key, 1);
			else *pv+=1;
		}

		memset(max, 0, sizeof(int)*n);
		memset(cnt, 0, sizeof(int)*n);
		for(int i=0; i<HASH_N; i++) {
			HashItem *p = h->a[i];
			while (p) {
				HashItem *q = p->next;
				//handle(p->key, p->value)
				int root = p->key/k, count = p->value;
				cnt[root] += count;
				if (count > max[root]) max[root] = count;
				p = q;
			}
		}
		int ans = 0;
		for(int i=0; i<n; i++) ans += cnt[i] - max[i];
		printf("%d\n", ans);
		OpenHash_clear(h);
		//break;
	}
}


//misc
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>

uint64_t hash_shift64(uint64_t key) {
	key = (~key) + (key << 21); // key = (key << 21) - key - 1;
	key = key ^ (key >> 24);
	key = (key + (key << 3)) + (key << 8); // key * 265
	key = key ^ (key >> 14);
	key = (key + (key << 2)) + (key << 4); // key * 21
	key = key ^ (key >> 28);
	key = key + (key << 31);
	return key;
}

#define KT uint64_t
#define VT int
#define EQ(a,b) ((a)==(b))
#define HASH_N 99991
#define HASH_F hash_shift64

typedef struct HashItem {
	KT key;
	VT value;
	size_t hash;
	struct HashItem *next;
} HashItem;

typedef struct OpenHash {
	int n;
	HashItem *a[HASH_N];
} OpenHash;

void OpenHash_init(OpenHash *self) {
	self->n = 0;
	memset(self->a, 0, sizeof(self->a));
}

int OpenHash_put(OpenHash *self, KT key, VT value) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			p->value = value;
			return 0;
		}
		p = p->next;
	}
	HashItem *x = malloc(sizeof(HashItem));
	x->key = key;
	x->value = value;
	x->hash = hash;
	x->next = self->a[idx];
	self->a[idx] = x;
	self->n ++;
	return 1;
}

VT *OpenHash_get(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			return &p->value;
		}
		p = p->next;
	}
	return NULL;
}

int OpenHash_del(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx], *prev=NULL;
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			if (prev==NULL) self->a[idx] = p->next;
			else prev->next = p->next;
			//NOTE: free p->key and p->value
			free(p);
			self->n--;
			return 1;
		}
		prev = p;
		p = p->next;
	}
	return 0;
}

void OpenHash_clear(OpenHash *self) {
	for(size_t i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		while (p) {
			HashItem *q = p->next;
			//NOTE: free p->key or p->value
			free(p);
			p = q;
		}
		self->a[i] = NULL;
	}
	self->n = 0;
}

void OpenHash_print(OpenHash *self, char *fmt) {
	printf("%d %d\n", self->n, HASH_N);
	for(int i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		if (p==NULL) continue;
		printf("%d", i);
		while(p) {
			printf(" %lu ", p->hash);
			printf(fmt, p->key, p->value);
			p = p->next;
		}
		printf("\n");
	}
}

//-----------------------------------------------------

int dsu_init(int *g, int n) {
	for(int i=0; i<n; i++) g[i] = i;
}

int dsu_find(int *g, int x) {
	int p=x, f;
	while(g[p] != p) p=g[p];
	while(g[x] != p) f=g[x], g[x]=p, x=f;
	return p;
}

void dsu_union(int *g, int x, int y) {
	g[dsu_find(g, y)] = dsu_find(g, x);
}

//-----------------------------------------------------

#define N 200000
int c[N];
int g[N];
int max[N];
int cnt[N];
OpenHash oh;

int main() {
	int n, m, k;
	OpenHash *h = &oh;
	while(scanf("%d %d %d", &n, &m, &k)==3) {
		OpenHash_init(h);
		dsu_init(g, n);
		for(int i=0; i<n; i++) {
			scanf("%d", &c[i]);
			c[i]--;
		}
		for(int i=0; i<m; i++) {
			int x,y;
			scanf("%d %d", &x, &y);
			dsu_union(g, x-1, y-1);
		}
		for(int i=0; i<n; i++) {
			int r = dsu_find(g, i);
			uint64_t key = (uint64_t)r*k + c[i]; //(r,c[i])
			int *pv = OpenHash_get(h, key);
			if (pv==NULL) OpenHash_put(h, key, 1);
			else *pv+=1;
		}

		memset(max, 0, sizeof(int)*n);
		memset(cnt, 0, sizeof(int)*n);
		for(int i=0; i<HASH_N; i++) {
			HashItem *p = h->a[i];
			while (p) {
				HashItem *q = p->next;
				//handle(p->key, p->value)
				int root = p->key/k, count = p->value;
				cnt[root] += count;
				if (count > max[root]) max[root] = count;
				p = q;
			}
		}
		int ans = 0;
		for(int i=0; i<n; i++) ans += cnt[i] - max[i];
		printf("%d\n", ans);
		OpenHash_clear(h);
		//break;
	}
}


//misc
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>

uint64_t hash_shift64(uint64_t key) {
	key = (~key) + (key << 21); // key = (key << 21) - key - 1;
	key = key ^ (key >> 24);
	key = (key + (key << 3)) + (key << 8); // key * 265
	key = key ^ (key >> 14);
	key = (key + (key << 2)) + (key << 4); // key * 21
	key = key ^ (key >> 28);
	key = key + (key << 31);
	return key;
}

#define KT uint64_t
#define VT int
#define EQ(a,b) ((a)==(b))
#define HASH_N 99991
#define HASH_F hash_shift64

typedef struct HashItem {
	KT key;
	VT value;
	size_t hash;
	struct HashItem *next;
} HashItem;

typedef struct OpenHash {
	int n;
	HashItem *a[HASH_N];
} OpenHash;

void OpenHash_init(OpenHash *self) {
	self->n = 0;
	memset(self->a, 0, sizeof(self->a));
}

int OpenHash_put(OpenHash *self, KT key, VT value) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			p->value = value;
			return 0;
		}
		p = p->next;
	}
	HashItem *x = malloc(sizeof(HashItem));
	x->key = key;
	x->value = value;
	x->hash = hash;
	x->next = self->a[idx];
	self->a[idx] = x;
	self->n ++;
	return 1;
}

VT *OpenHash_get(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			return &p->value;
		}
		p = p->next;
	}
	return NULL;
}

int OpenHash_del(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx], *prev=NULL;
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			if (prev==NULL) self->a[idx] = p->next;
			else prev->next = p->next;
			//NOTE: free p->key and p->value
			free(p);
			self->n--;
			return 1;
		}
		prev = p;
		p = p->next;
	}
	return 0;
}

void OpenHash_clear(OpenHash *self) {
	for(size_t i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		while (p) {
			HashItem *q = p->next;
			//NOTE: free p->key or p->value
			free(p);
			p = q;
		}
		self->a[i] = NULL;
	}
	self->n = 0;
}

void OpenHash_print(OpenHash *self, char *fmt) {
	printf("%d %d\n", self->n, HASH_N);
	for(int i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		if (p==NULL) continue;
		printf("%d", i);
		while(p) {
			printf(" %lu ", p->hash);
			printf(fmt, p->key, p->value);
			p = p->next;
		}
		printf("\n");
	}
}

//-----------------------------------------------------

int dsu_init(int *g, int n) {
	for(int i=0; i<n; i++) g[i] = i;
}

int dsu_find(int *g, int x) {
	int p=x, f;
	while(g[p] != p) p=g[p];
	while(g[x] != p) f=g[x], g[x]=p, p=f;
	return p;
}

int dsu_union(int *g, int x, int y) {
	g[dsu_find(g, y)] = dsu_find(g, x);
}

//-----------------------------------------------------

#define N 200000
int c[N];
int g[N];
int max[N];
int cnt[N];
OpenHash oh;

int main() {
	int n, m, k;
	OpenHash *h = &oh;
	while(scanf("%d %d %d", &n, &m, &k)==3) {
		dsu_init(g, n);
		for(int i=0; i<n; i++) {
			scanf("%d", &c[i]);
			c[i]--;
		}
		for(int i=0; i<m; i++) {
			int x,y;
			scanf("%d %d", &x, &y);
			dsu_union(g, x-1, y-1);
		}
		for(int i=0; i<n; i++) {
			int r = dsu_find(g, i);
			int key = r*k+c[i]; //(r,c[i])
			int *pv = OpenHash_get(h, key);
			if (pv==NULL) OpenHash_put(h, key, 1);
			else *pv+=1;
		}

		memset(max, 0, sizeof(int)*n);
		memset(cnt, 0, sizeof(int)*n);
		for(int i=0; i<HASH_N; i++) {
			HashItem *p = h->a[i];
			while (p) {
				HashItem *q = p->next;
				//handle(p->key, p->value)
				int root = p->key/k, count = p->value;
				cnt[root] += count;
				if (count > max[root]) max[root] = count;
				p = q;
			}
		}
		int ans = 0;
		for(int i=0; i<n; i++) {
			ans += cnt[i] - max[i];
		}
		printf("%d\n", ans);
		OpenHash_clear(h);
		//break;
	}
}


//misc
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>

uint64_t hash_shift64(uint64_t key) {
	key = (~key) + (key << 21); // key = (key << 21) - key - 1;
	key = key ^ (key >> 24);
	key = (key + (key << 3)) + (key << 8); // key * 265
	key = key ^ (key >> 14);
	key = (key + (key << 2)) + (key << 4); // key * 21
	key = key ^ (key >> 28);
	key = key + (key << 31);
	return key;
}

#define KT uint64_t
#define VT int
#define EQ(a,b) ((a)==(b))
#define HASH_N 99991
#define HASH_F hash_shift64

typedef struct HashItem {
	KT key;
	VT value;
	size_t hash;
	struct HashItem *next;
} HashItem;

typedef struct OpenHash {
	int n;
	HashItem *a[HASH_N];
} OpenHash;

void OpenHash_init(OpenHash *self) {
	self->n = 0;
	memset(self->a, 0, sizeof(self->a));
}

int OpenHash_put(OpenHash *self, KT key, VT value) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			p->value = value;
			return 0;
		}
		p = p->next;
	}
	HashItem *x = malloc(sizeof(HashItem));
	x->key = key;
	x->value = value;
	x->hash = hash;
	x->next = self->a[idx];
	self->a[idx] = x;
	self->n ++;
	return 1;
}

VT *OpenHash_get(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			return &p->value;
		}
		p = p->next;
	}
	return NULL;
}

int OpenHash_del(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx], *prev=NULL;
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			if (prev==NULL) self->a[idx] = p->next;
			else prev->next = p->next;
			//NOTE: free p->key and p->value
			free(p);
			self->n--;
			return 1;
		}
		prev = p;
		p = p->next;
	}
	return 0;
}

void OpenHash_clear(OpenHash *self) {
	for(size_t i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		while (p) {
			HashItem *q = p->next;
			//NOTE: free p->key or p->value
			free(p);
			p = q;
		}
		self->a[i] = NULL;
	}
	self->n = 0;
}

void OpenHash_print(OpenHash *self, char *fmt) {
	printf("%d %d\n", self->n, HASH_N);
	for(int i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		if (p==NULL) continue;
		printf("%d", i);
		while(p) {
			printf(" %lu ", p->hash);
			printf(fmt, p->key, p->value);
			p = p->next;
		}
		printf("\n");
	}
}

//-----------------------------------------------------

int dsu_init(int *g, int n) {
	for(int i=0; i<n; i++) g[i] = i;
}

int dsu_find(int *g, int x) {
	int p=x, f;
	while(g[p] != p) p=g[p];
	while(g[x] != p) f=g[x], g[x]=p, p=f;
	return p;
}

int dsu_union(int *g, int x, int y) {
	g[dsu_find(g, y)] = dsu_find(g, x);
}

//-----------------------------------------------------

#define N 200000
int c[N];
int g[N];
OpenHash oh;

int main() {
	int n, m, k;
	OpenHash *h = &oh;
	while(scanf("%d %d %d", &n, &m, &k)==3) {
		dsu_init(g, n);
		for(int i=0; i<n; i++) {
			scanf("%d", &c[i]);
			c[i]--;
		}
		for(int i=0; i<m; i++) {
			int x,y;
			scanf("%d %d", &x, &y);
			dsu_union(g, x-1, y-1);
		}
		for(int i=0; i<n; i++) {
			int r = dsu_find(g, i);
			int key = r*k+c[i]; //(r,c[i])
			int *pv = OpenHash_get(h, key);
			if (pv==NULL) OpenHash_put(h, key, 1);
			else *pv+=1;
		}

		int cur=-1, max, count;
		int ans = 0;
		for(int i=0; i<HASH_N; i++) {
			HashItem *p = h->a[i];
			while (p) {
				HashItem *q = p->next;
				int root = p->key/k, cnt = p->value;
				if (root==cur) {
					if (cnt>max) max = cnt;
					count += cnt;
				}
				else {
					ans += count-max;
					cur = root;
					max = 0;
					count = 0;
				}
				//handle(p->key, p->value)
				p = q;
			}
		}
		ans += count-max;
		printf("%d\n", count);
	}
}


//misc
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>

uint64_t hash_shift64(uint64_t key) {
	key = (~key) + (key << 21); // key = (key << 21) - key - 1;
	key = key ^ (key >> 24);
	key = (key + (key << 3)) + (key << 8); // key * 265
	key = key ^ (key >> 14);
	key = (key + (key << 2)) + (key << 4); // key * 21
	key = key ^ (key >> 28);
	key = key + (key << 31);
	return key;
}

#define KT uint64_t
#define VT int
#define EQ(a,b) ((a)==(b))
#define HASH_N 99991
#define HASH_F hash_shift64

typedef struct HashItem {
	KT key;
	VT value;
	size_t hash;
	struct HashItem *next;
} HashItem;

typedef struct OpenHash {
	int n;
	HashItem *a[HASH_N];
} OpenHash;

void OpenHash_init(OpenHash *self) {
	self->n = 0;
	memset(self->a, 0, sizeof(self->a));
}

int OpenHash_put(OpenHash *self, KT key, VT value) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			p->value = value;
			return 0;
		}
		p = p->next;
	}
	HashItem *x = malloc(sizeof(HashItem));
	x->key = key;
	x->value = value;
	x->hash = hash;
	x->next = self->a[idx];
	self->a[idx] = x;
	self->n ++;
	return 1;
}

VT *OpenHash_get(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx];
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			return &p->value;
		}
		p = p->next;
	}
	return NULL;
}

int OpenHash_del(OpenHash *self, KT key) {
	size_t hash = HASH_F(key), idx = hash % HASH_N;
	HashItem *p = self->a[idx], *prev=NULL;
	while (p) {
		if (hash==p->hash && EQ(key, p->key)) {
			if (prev==NULL) self->a[idx] = p->next;
			else prev->next = p->next;
			//NOTE: free p->key and p->value
			free(p);
			self->n--;
			return 1;
		}
		prev = p;
		p = p->next;
	}
	return 0;
}

void OpenHash_clear(OpenHash *self) {
	for(size_t i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		while (p) {
			HashItem *q = p->next;
			//NOTE: free p->key or p->value
			free(p);
			p = q;
		}
		self->a[i] = NULL;
	}
	self->n = 0;
}

void OpenHash_print(OpenHash *self, char *fmt) {
	printf("%d %d\n", self->n, HASH_N);
	for(int i=0; i<HASH_N; i++) {
		HashItem *p = self->a[i];
		if (p==NULL) continue;
		printf("%d", i);
		while(p) {
			printf(" %lu ", p->hash);
			printf(fmt, p->key, p->value);
			p = p->next;
		}
		printf("\n");
	}
}

//-----------------------------------------------------

int dsu_init(int *g, int n) {
	for(int i=0; i<n; i++) g[i] = i;
}

int dsu_find(int *g, int x) {
	int p=x, f;
	while(g[p] != p) p=g[p];
	while(g[x] != p) f=g[x], g[x]=p, p=f;
	return p;
}

int dsu_union(int *g, int x, int y) {
	g[dsu_find(g, y)] = dsu_find(g, x);
}

//-----------------------------------------------------

#define N 200000
int c[N];
int g[N];
OpenHash oh;

int main() {
	int n, m, k;
	OpenHash *h = &oh;
	while(scanf("%d %d %d", &n, &m, &k)==3) {
		dsu_init(g, n);
		for(int i=0; i<n; i++) {
			scanf("%d", &c[i]);
			c[i]--;
		}
		for(int i=0; i<m; i++) {
			int x,y;
			scanf("%d %d", &x, &y);
			dsu_union(g, x-1, y-1);
		}
		for(int i=0; i<n; i++) {
			int r = dsu_find(g, i);
			int key = r*k+c[i]; //(r,c[i])
			int *pv = OpenHash_get(h, key);
			if (pv==NULL) OpenHash_put(h, key, 1);
			else *pv+=1;
		}

		int cur=-1, max, count;
		int ans = 0;
		for(int i=0; i<HASH_N; i++) {
			HashItem *p = h->a[i];
			while (p) {
				HashItem *q = p->next;
				int root = p->key/k, cnt = p->value;
				if (root==cur) {
					if (cnt>max) max = cnt;
					count += cnt;
				}
				else {
					ans += count-max;
					cur = root;
					max = 0;
					count = 0;
				}
				//handle(p->key, p->value)
				p = q;
			}
		}
		ans += count-max;
		printf("%d\n", count);
	}
}


#include<stdio.h>
#include<stdlib.h>

typedef struct __st_List{
    int ind;
    struct __st_List *next;
}LIST;

void ins(int, int);
void dfs(int);

int ver[200005], cnt[200005], flg[200005], col[200005], n, m, k, max, sum, c_ver;
LIST *adj[200005];

int main(){
    int i, j, l, r, ans;

    for(i=0;i<200005;i++){
	ver[i]=-1;
	cnt[i]=0;
	flg[i] = -1;
	adj[i] = NULL;
    }
    scanf("%d %d %d", &n, &m, &k);
    for(i = 0;i<n;i++){
	scanf("%d", &j);
	col[i] = j-1;
    }

    for(i = 0; i<m;i++){
	scanf("%d %d", &l, &r);
	ins(l-1, r-1);
	ins(r-1, l-1);
    }

    ans = 0;
    for(i = 0;i<n;i++){
	if(flg[i] == -1){
	    c_ver = i;
	    max = 0;
	    sum = 0;
	    dfs(i);
	    ans += sum - max;
	}
    }
    printf("%d\n", ans);

    return 0;
}

void ins(int i, int j){
    LIST *tmp = (LIST *)malloc(sizeof(LIST));
    tmp->ind = j;
    tmp->next = adj[i];
    adj[i] = tmp;
}

void dfs(int x){
    LIST *tmp;

    if(flg[x] != -1)
	return ;
    flg[x] = 0;
    if(ver[col[x]] != c_ver){
	ver[col[x]] = c_ver;
	cnt[col[x]] = 0;
    }
    cnt[col[x]]++;
    sum++;
    if(cnt[col[x]] > max)
	max = cnt[col[x]];

    tmp = adj[x];
    while(tmp){
	dfs(tmp->ind);
	tmp = tmp->next;
    }
}


#include <stdio.h>
#include <stdlib.h>
#define NMAX 200010
//#define DEBUG

struct ListElement {
	int v;
	struct ListElement *next;
};
typedef struct ListElement le_t;

int n, m, k, color[NMAX],
	count[NMAX], status[NMAX];
le_t *adj[NMAX], *component;

le_t *Make(int v, le_t *next) {
	le_t *p = (le_t *)malloc(sizeof(le_t));
	p->v = v;
	p->next = next;
	return p;
}

void Push_front(int v, le_t **top) {
	*top = Make(v, *top);
}

void Read(void) {
	int i, u, v;

	scanf("%d%d%d", &n, &m, &k);

	for(i = 1; i <= n; ++i)
		scanf("%d", color + i);

	for(i = 0; i < m; ++i) {
		scanf("%d%d", &u, &v);
		Push_front(v, adj + u);
		Push_front(u, adj + v);
	}
}

void DFS(int u) {
	le_t *p;

	++count[color[u]];
	Push_front(u, &component);

	status[u] = 1;
	for(p = adj[u]; p != NULL; p = p->next)
		if (!status[p->v])
			DFS(p->v);
	status[u] = 2;
}

void Zeroing_count(void) {
	le_t *p;
	for(p = component; p != NULL; p = p->next)
		count[color[p->v]] = 0;
}

void Free_list(le_t **top) {
	if (top == NULL)
		return;

	le_t *p;
	while (*top != NULL) {
		p = *top;
		*top = (*top)->next;
		free(p);
	}
}

int Count_except_max(void) {
	le_t *p;
	int max_color = 0, c = 0;
	for(p = component; p != NULL; p = p->next)
		if (count[max_color] < count[color[p->v]])
			max_color = color[p->v];

	for(p = component; p != NULL; p = p->next)
		if (color[p->v] != max_color)
			c += count[color[p->v]];

	return c;
}

void Write_list(le_t *top) {
	for(; top != NULL; top = top->next)
		printf("%d ", top->v);
	printf("\n");
}

int DFS_TREE(void) {
	int u, colored = 0;
	for(u = 1; u <= n; ++u)
		if (!status[u]) {
			Zeroing_count();
			DFS(u);
			colored += Count_except_max();
			Free_list(&component);
		}
	return colored;
}

int main(void) {
	#ifdef DEBUG
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#endif

	Read();

	printf("%d", DFS_TREE());

	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#define NMAX 200010
//#define DEBUG

struct ListElement {
	int v;
	struct ListElement *next;
};
typedef struct ListElement le_t;

int n, m, k, color[NMAX],
	count[NMAX], status[NMAX], isAdded[NMAX];
le_t *adj[NMAX], *component;

le_t *Make(int v, le_t *next) {
	le_t *p = (le_t *)malloc(sizeof(le_t));
	p->v = v;
	p->next = next;
	return p;
}

void Push_front(int v, le_t **top) {
	*top = Make(v, *top);
}

void Read(void) {
	int i, u, v;

	scanf("%d%d%d", &n, &m, &k);

	for(i = 1; i <= n; ++i)
		scanf("%d", color + i);

	for(i = 0; i < m; ++i) {
		scanf("%d%d", &u, &v);
		Push_front(v, adj + u);
		Push_front(u, adj + v);
	}
}

void DFS(int u) {
	le_t *p;

	++count[color[u]];
	Push_front(u, &component);

	status[u] = 1;
	for(p = adj[u]; p != NULL; p = p->next)
		if (!status[p->v])
			DFS(p->v);
	status[u] = 2;
}

void Zeroing_by_component(int *arr) {
	le_t *p;
	for(p = component; p != NULL; p = p->next)
		arr[color[p->v]] = 0;
}

void Free_list(le_t **top) {
	if (top == NULL)
		return;

	le_t *p;
	while (*top != NULL) {
		p = *top;
		*top = (*top)->next;
		free(p);
	}
}

int Count_except_max(void) {
	le_t *p;
	int max_color = 0, c = 0;
	for(p = component; p != NULL; p = p->next)
		if (count[max_color] < count[color[p->v]])
			max_color = color[p->v];

	for(p = component; p != NULL; p = p->next)
		if (color[p->v] != max_color && !isAdded[color[p->v]]) {
			c += count[color[p->v]];
			isAdded[color[p->v]] = 1;
		}

	return c;
}

void Write_list(le_t *top) {
	for(; top != NULL; top = top->next)
		printf("%d ", top->v);
	printf("\n");
}

int DFS_TREE(void) {
	int u, colored = 0;
	for(u = 1; u <= n; ++u)
		if (!status[u]) {
			DFS(u);
			colored += Count_except_max();
			Zeroing_by_component(count);
			Zeroing_by_component(isAdded);
			Free_list(&component);
		}
	return colored;
}

int main(void) {
	#ifdef DEBUG
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#endif

	Read();

	printf("%d", DFS_TREE());

	return 0;
}


#pragma comment(linker, "/STACK:60000000")

#include <stdio.h>
#include <stdlib.h>
#define NMAX 200010
//#define DEBUG

struct ListElement {
	int v;
	struct ListElement *next;
};
typedef struct ListElement le_t;

int n, m, k, color[NMAX],
	count[NMAX], status[NMAX], max_color;
le_t *adj[NMAX];

le_t *Make(int v, le_t *next) {
	le_t *p = (le_t *)malloc(sizeof(le_t));
	p->v = v;
	p->next = next;
	return p;
}

void Push_front(int v, le_t **top) {
	*top = Make(v, *top);
}

void Read(void) {
	int i, u, v;

	scanf("%d%d%d", &n, &m, &k);

	for(i = 1; i <= n; ++i)
		scanf("%d", color + i);

	for(i = 0; i < m; ++i) {
		scanf("%d%d", &u, &v);
		Push_front(v, adj + u);
		Push_front(u, adj + v);
	}
}

void DFS(int u) {
	le_t *p;

	++count[color[u]];
	if (count[max_color] < count[color[u]])
		max_color = color[u];

	status[u] = 1;
	for(p = adj[u]; p != NULL; p = p->next)
		if (!status[p->v])
			DFS(p->v);
	status[u] = 2;
}

void Zeroing(int n, int *arr) {
	int i;
	for(i = 0; i <= k; ++i)
		arr[i] = 0;
}

int Count_except(int max_color) {
	int i, c = 0;
	for(i = 1; i <= k; ++i)
		if (i != max_color)
			c += count[i];
	return c;
}

int DFS_TREE(void) {
	int u, colored = 0;
	for(u = 1; u <= n; ++u)
		if (!status[u]) {
			Zeroing(k, count);
			max_color = 0;
			DFS(u);
			colored += Count_except(max_color);
		}
	return colored;
}

int main(void) {
	#ifdef DEBUG
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#endif

	Read();

	printf("%d", DFS_TREE());

	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#define NMAX 200010
//#define DEBUG

struct ListElement {
	int v;
	struct ListElement *next;
};
typedef struct ListElement le_t;

int n, m, k, color[NMAX],
	count[NMAX], status[NMAX];
le_t *adj[NMAX], *component;

le_t *Make(int v, le_t *next) {
	le_t *p = (le_t *)malloc(sizeof(le_t));
	p->v = v;
	p->next = next;
	return p;
}

void Push_front(int v, le_t **top) {
	*top = Make(v, *top);
}

void Read(void) {
	int i, u, v;

	scanf("%d%d%d", &n, &m, &k);

	for(i = 1; i <= n; ++i)
		scanf("%d", color + i);

	for(i = 0; i < m; ++i) {
		scanf("%d%d", &u, &v);
		Push_front(v, adj + u);
		Push_front(u, adj + v);
	}
}

void DFS(int u) {
	le_t *p;

	++count[color[u]];
	Push_front(u, &component);

	status[u] = 1;
	for(p = adj[u]; p != NULL; p = p->next)
		if (!status[p->v])
			DFS(p->v);
	status[u] = 2;
}

void Zeroing_count(void) {
	le_t *p;
	for(p = component; p != NULL; p = p->next)
		count[color[p->v]] = 0;
}

void Free_list(le_t **top) {
	if (top == NULL)
		return;

	le_t *p;
	while (*top != NULL) {
		p = *top;
		*top = (*top)->next;
		free(p);
	}
}

int Count_except_max(void) {
	le_t *p;
	int max_color = 0, c = 0;
	for(p = component; p != NULL; p = p->next)
		if (count[max_color] < count[color[p->v]])
			max_color = color[p->v];

	for(p = component; p != NULL; p = p->next)
		if (color[p->v] != max_color)
			c += count[color[p->v]];

	return c;
}

void Write_list(le_t *top) {
	for(; top != NULL; top = top->next)
		printf("%d ", top->v);
	printf("\n");
}

int DFS_TREE(void) {
	int u, colored = 0;
	for(u = 1; u <= n; ++u)
		if (!status[u]) {
			DFS(u);
			colored += Count_except_max();
			Zeroing_count();
			Free_list(&component);
		}
	return colored;
}

int main(void) {
	#ifdef DEBUG
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#endif

	Read();

	printf("%d", DFS_TREE());

	return 0;
}


import java.util.*;
import java.io.*;
public class MainClass
{
    static int[] count;
    static ArrayList<Integer>[] adj;
    static boolean[] visited;
    static boolean[] visited1;
    static int max = 0;
    static int size = 0;
    static int[] A;
    public static void main(String[] args) throws IOException
    {
        Reader in = new Reader();
        int n = in.nextInt();
        int m = in.nextInt();
        int k = in.nextInt();
        A = new int[n];
        for (int i=0;i<n;i++)
            A[i] = in.nextInt() - 1;
        count = new int[k];
        adj = new ArrayList[n];
        visited = new boolean[n];
        visited1 = new boolean[n];
        HashSet<Integer>[] adj1 = new HashSet[n];
        for (int i=0;i<n;i++)
        {
            adj1[i] = new HashSet<>();
            adj[i] = new ArrayList<>();
        }
        for (int i=0;i<m;i++)
        {
            int x = in.nextInt() - 1;
            int y = in.nextInt() - 1;
            if (adj1[x].contains(y))    continue;
            adj[x].add(y);
            adj[y].add(x);
            adj1[x].add(y);
            adj1[y].add(x);

        }
        int ans = 0;
        for (int i=0;i<n;i++)
        {
            if (!visited[i])
            {
                size = 0;
                max = 1;
                explore(i);
                erase(i);
                ans += size - max;
            }
        }
        System.out.println(ans);
    }
    public static void explore(int v)
    {
        visited[v] = true;
        size++;
        count[A[v]]++;
        max = Math.max(max, count[A[v]]);
        for (int u: adj[v]) if (!visited[u])    explore(u);
    }
    public static void erase(int v)
    {
        visited1[v] = true;
        count[A[v]] = 0;
        for (int u: adj[v]) if (!visited1[u])   erase(u);
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}


import java.util.*;
import java.io.*;
public class MainClass
{
    public static void main(String[] args) throws IOException
    {
        Reader in = new Reader();
        int n = in.nextInt();
        int m = in.nextInt();
        int k = in.nextInt();
        int[] A = new int[n];
        for (int i=0;i<n;i++)
            A[i] = in.nextInt();
        DSU DSU = new DSU(n);
        for (int i=0;i<n;i++)
            DSU.makeSet(i, A[i]);
        for (int i=0;i<m;i++)
        {
            int x = in.nextInt() - 1;
            int y = in.nextInt() - 1;
            DSU.unionSets(x, y);
        }
        HashSet<Integer> h = new HashSet<>();
        int ans = 0;
        for (int i=0;i<n;i++)
        {
            int x = DSU.findSet(i);
            if (!h.contains(x))
            {
                h.add(x);
                ans += DSU.size[x] - DSU.max[x];
            }
        }
        System.out.println(ans);
    }
}
class DSU
{
    int[] parent;
    int[] size;
    ArrayList<Integer>[] adj;
    int[] max;

    DSU(int n)
    {
        this.parent = new int[n];
        this.size = new int[n];
        Arrays.fill(parent, -1);
        adj = new ArrayList[n];
        max = new int[n];
    }

    public void makeSet(int v, int color)
    {
        parent[v] = v;
        size[v] = 1;
        adj[v] = new ArrayList<>();
        adj[v].add(color);
        max[v] = 1;
    }

    public int findSet(int v)
    {
        if (v == parent[v]) return v;
        return parent[v] = findSet(parent[v]);
    }

    public void unionSets(int a, int b)
    {
        a = findSet(a);
        b = findSet(b);
        if (a != b)
        {
            if (size[a] < size[b])
            {
                int temp = a;
                a = b;
                b = temp;
            }
            parent[b] = a;
            size[a] += size[b];
            int i = 0;
            int j = 0;
            ArrayList<Integer> C = new ArrayList<>();
            while (i < adj[a].size() && j < adj[b].size())
            {
                if (adj[a].get(i) < adj[b].get(j))
                {
                    C.add(adj[a].get(i++));
                }
                else
                {
                    C.add(adj[b].get(j++));
                }
            }
            while (i < adj[a].size())
                C.add(adj[a].get(i++));
            while (j < adj[b].size())
                C.add(adj[b].get(j++));
            adj[a].clear();
            adj[a].addAll(C);
            int mm = max[a];
            for (int ii=0;ii<C.size();ii++)
            {
                int jj = ii;
                while (jj < C.size() && (int)C.get(jj) == (int)C.get(ii)) jj++;
                mm = Math.max(mm, jj - ii);
                ii = jj - 1;
            }
            max[a] = Math.max(mm, max[a]);
        }
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}


import java.util.*;
import java.io.*;
public class MainClass
{
    public static void main(String[] args) throws IOException
    {
        Reader in = new Reader();
        int n = in.nextInt();
        int m = in.nextInt();
        int k = in.nextInt();
        int[] A = new int[n];
        for (int i=0;i<n;i++)
            A[i] = in.nextInt();
        int[] p1 = new int[m];
        int[] p2 = new int[m];
        DSU DSU = new DSU(n);
        for (int i=0;i<n;i++)
            DSU.makeSet(i, A[i]);
        for (int i=0;i<m;i++)
        {
            int x = in.nextInt() - 1;
            int y = in.nextInt() - 1;
            DSU.unionSets(x, y);
        }
        HashSet<Integer> h = new HashSet<>();
        int ans = 0;
        for (int i=0;i<n;i++)
        {
            int x = DSU.findSet(i);
            if (!h.contains(x))
            {
                h.add(x);
                ans += DSU.size[x] - DSU.max[x];
            }
        }
        System.out.println(ans);
    }
}
class DSU
{
    int[] parent;
    int[] size;
    HashMap<Integer, Integer>[] adj;
    int max[];

    DSU(int n)
    {
        this.parent = new int[n];
        this.size = new int[n];
        Arrays.fill(parent, -1);
        adj = new HashMap[n];
        max = new int[n];
    }

    public void makeSet(int v, int color)
    {
        parent[v] = v;
        size[v] = 1;
        adj[v] = new HashMap<>();
        adj[v].put(color, 1);
        max[v] = 1;
    }

    public int findSet(int v)
    {
        if (v == parent[v]) return v;
        return parent[v] = findSet(parent[v]);
    }

    public void unionSets(int a, int b)
    {
        a = findSet(a);
        b = findSet(b);
        if (a != b)
        {
            if (size[a] < size[b])
            {
                int temp = a;
                a = b;
                b = temp;
            }
            parent[b] = a;
            size[a] += size[b];
            HashMap<Integer, Integer> h2 = new HashMap<>();
            for (int i: adj[a].keySet())
            {
                if (adj[b].containsKey(i))
                {
                    int val = adj[a].get(i) + adj[b].get(i);
                    h2.put(i, val);
                    max[a] = Math.max(max[a], val);
                }
                else
                {
                    int val = adj[a].get(i);
                    h2.put(i, val);
                    max[a] = Math.max(max[a], val);
                }
            }
            for (int i: adj[b].keySet())
            {
                if (!adj[a].containsKey(i))
                {
                    int val = adj[b].get(i);
                    h2.put(i, val);
                    max[a] = Math.max(max[a], val);
                }
            }
        }
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}


import java.util.*;
import java.io.*;
public class MainClass
{
    static int[] count;
    static ArrayList<Integer>[] adj;
    static boolean[] visited;
    static int max = 0;
    static int size = 0;
    static int[] A;
    public static void main(String[] args) throws IOException
    {
        Reader in = new Reader();
        int n = in.nextInt();
        int m = in.nextInt();
        int k = in.nextInt();
        A = new int[n];
        for (int i=0;i<n;i++)
            A[i] = in.nextInt() - 1;
        count = new int[k];
        adj = new ArrayList[n];
        visited = new boolean[n];
        HashSet<Integer>[] adj1 = new HashSet[n];
        for (int i=0;i<n;i++)
        {
            adj1[i] = new HashSet<>();
            adj[i] = new ArrayList<>();
        }
        for (int i=0;i<m;i++)
        {
            int x = in.nextInt() - 1;
            int y = in.nextInt() - 1;
            if (adj1[x].contains(y))    continue;
            adj[x].add(y);
            adj[y].add(x);
            adj1[x].add(y);
            adj1[y].add(x);

        }
        int ans = 0;
        for (int i=0;i<n;i++)
        {
            if (!visited[i])
            {
                size = 0;
                max = 1;
                explore(i);
                ans += size - max;
            }
        }
        System.out.println(ans);
    }
    public static void explore(int v)
    {
        visited[v] = true;
        size++;
        count[A[v]]++;
        max = Math.max(max, count[A[v]]);
        for (int u: adj[v]) if (!visited[u])    explore(u);
        count[A[v]] = 0;
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}


import java.util.*;
import java.io.*;
public class MainClass
{
    static int[] count;
    static ArrayList<Integer>[] adj;
    static boolean[] visited;
    static int max = 0;
    static int size = 0;
    static int[] A;
    public static void main(String[] args) throws IOException
    {
        Reader in = new Reader();
        int n = in.nextInt();
        int m = in.nextInt();
        int k = in.nextInt();
        A = new int[n];
        for (int i=0;i<n;i++)
            A[i] = in.nextInt() - 1;
        count = new int[k];
        adj = new ArrayList[n];
        visited = new boolean[n];
        HashSet<Integer>[] adj1 = new HashSet[n];
        for (int i=0;i<n;i++)
        {
            adj1[i] = new HashSet<>();
            adj[i] = new ArrayList<>();
        }
        for (int i=0;i<m;i++)
        {
            int x = in.nextInt() - 1;
            int y = in.nextInt() - 1;
            if (adj1[x].contains(y))    continue;
            adj[x].add(y);
            adj[y].add(x);
            adj1[x].add(y);
            adj1[y].add(x);

        }
        int ans = 0;
        for (int i=0;i<n;i++)
        {
            if (!visited[i])
            {
                size = 0;
                max = 1;
                explore(i);
                ans += size - max;
                Arrays.fill(count, 0);
            }
        }
        System.out.println(ans);
    }
    public static void explore(int v)
    {
        visited[v] = true;
        size++;
        count[A[v]]++;
        max = Math.max(max, count[A[v]]);
        for (int u: adj[v]) if (!visited[u])    explore(u);
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}


import java.util.*;
import java.io.*;
public class MainClass
{
    static int[] count;
    static ArrayList<Integer>[] adj;
    static boolean[] visited;
    static int max = 0;
    static int size = 0;
    static int[] A;
    public static void main(String[] args) throws IOException
    {
        Reader in = new Reader();
        int n = in.nextInt();
        int m = in.nextInt();
        int k = in.nextInt();
        A = new int[n];
        for (int i=0;i<n;i++)
            A[i] = in.nextInt() - 1;
        count = new int[k];
        adj = new ArrayList[n];
        visited = new boolean[n];
        for (int i=0;i<n;i++)
            adj[i] = new ArrayList<>();
        for (int i=0;i<m;i++)
        {
            int x = in.nextInt() - 1;
            int y = in.nextInt() - 1;
            adj[x].add(y);
            adj[y].add(x);
        }
        int ans = 0;
        for (int i=0;i<n;i++)
        {
            if (!visited[i])
            {
                size = 0;
                max = 1;
                explore(i);
                ans += size - max;
            }
        }
        System.out.println(ans);
    }
    public static void explore(int v)
    {
        visited[v] = true;
        size++;
        count[A[v]]++;
        max = Math.max(max, count[A[v]]);
        for (int u: adj[v]) if (!visited[u])    explore(u);
        count[A[v]]--;
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

    public Reader()
    {
        din = new DataInputStream(System.in);
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public Reader(String file_name) throws IOException
    {
        din = new DataInputStream(new FileInputStream(file_name));
        buffer = new byte[BUFFER_SIZE];
        bufferPointer = bytesRead = 0;
    }

    public String readLine() throws IOException
    {
        byte[] buf = new byte[64]; // line length
        int cnt = 0, c;
        while ((c = read()) != -1)
        {
            if (c == '\n')
                break;
            buf[cnt++] = (byte) c;
        }
        return new String(buf, 0, cnt);
    }

    public int nextInt() throws IOException
    {
        int ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do
        {
            ret = ret * 10 + c - '0';
        }  while ((c = read()) >= '0' && c <= '9');

        if (neg)
            return -ret;
        return ret;
    }

    public long nextLong() throws IOException
    {
        long ret = 0;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();
        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');
        if (neg)
            return -ret;
        return ret;
    }

    public double nextDouble() throws IOException
    {
        double ret = 0, div = 1;
        byte c = read();
        while (c <= ' ')
            c = read();
        boolean neg = (c == '-');
        if (neg)
            c = read();

        do {
            ret = ret * 10 + c - '0';
        }
        while ((c = read()) >= '0' && c <= '9');

        if (c == '.')
        {
            while ((c = read()) >= '0' && c <= '9')
            {
                ret += (c - '0') / (div *= 10);
            }
        }

        if (neg)
            return -ret;
        return ret;
    }

    private void fillBuffer() throws IOException
    {
        bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
        if (bytesRead == -1)
            buffer[0] = -1;
    }

    private byte read() throws IOException
    {
        if (bufferPointer == bytesRead)
            fillBuffer();
        return buffer[bufferPointer++];
    }

    public void close() throws IOException
    {
        if (din == null)
            return;
        din.close();
    }
}