// Lupus Nocawy 17 V 2014, PA2014
// http://potyczki.mimuw.edu.pl/
// Runda 5
// Zadanie: FIO
// Fiolki [B]

#include <cstdio>
#include <iostream>
#include <cassert>
#include <cstring>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <cmath>
using namespace std;
#define REP(i,n) for(int i=0, _n=n; i<_n; ++i)
#define FOR(i,a,b) for(int i=(a), _b=(b); i<=_b; ++i)
#define FORD(i,a,b) for(int i=(a), _b=(b); i>=_b; --i)
#define IT(i,x) __typeof__(x) i=x
#define FOREACH(it,x) for(__typeof__((x).begin()) it=(x).begin(); it!=(x).end(); ++it)
#define ALL(x) x.begin(),x.end()
#define MP make_pair
#define PB push_back
#define DEBUG(x) if(debug) cout << x << endl;
typedef long long int lli;
typedef unsigned long long int llu;
typedef pair<int,int> pii;
const int debug=0;

const int INF = 2147483647;
const int max_n = 200000;
const int max_m = 200000;
const int max_k = 500000;

class reaction{
public:
	int a,b;	// reagents
	int dist;	// distance between reagents in the final vial
	int prio;	// the original priority of this reaction
	reaction(int a,int b,int dist,int prio): a(a), b(b), dist(dist), prio(prio) {}
};

bool operator< (const reaction &X, const reaction &Y){
	return X.dist < Y.dist;
}
bool reaction_greater (const reaction &X, const reaction &Y){
	return X.dist > Y.dist;
}
//bool reaction_prio (const reaction &X, const reaction &Y){
//	return X.prio < Y.prio;
//}
class reaction_prio{
public:
	bool operator() (const reaction &X, const reaction &Y){
		return X.prio > Y.prio;
	}
};

int main(void){
	int n,m,k;
	scanf("%d %d %d ", &n, &m, &k);
	vector<int> g(n);
	REP(i,n){
		scanf("%d ", &g[i]);
	}
	//REP(i,n){printf("%d ", g[i]);} printf("\n");
	vector<pii> seq(m);
	REP(i,m){
		int a,b;
		scanf("%d %d ", &a, &b);
		seq[i] = MP(a-1, b-1);
	}
	vector<pii> react(k);
	REP(i,k){
		int c,d;
		scanf("%d %d ", &c, &d);
		react[i] = MP(c-1,d-1);
	}

	vector<int> id_final(n);	// the vial number in which element ends
	vector<int> pos_final(n);	// position in final vial
	vector<list<int> > L(n);
	REP(i,n){	// construct empty vials
		L[i].PB(i);
	}
	REP(i,m){	// simulate merging vials
		int a = seq[i].first;
		int b = seq[i].second;
		//printf("%d %d\n", a,b);
		L[b].splice(L[b].begin(),L[a]);
	}
	REP(i,n){	// calculate position in final vial
		//printf("%d: ", i); 
		if(!L[i].empty()){
			int j=0;
			FOREACH(it,L[i]){
				id_final[*it] = i;
				pos_final[*it] = j++;
				//printf("%d ",*it);
			}
		}
		//printf("\n");
	}

	vector<vector<reaction> > Rv(n);
	vector<list<reaction> > R(n);
	REP(i,k){
		int a = react[i].first;
		int b = react[i].second;
		if(id_final[a]==id_final[b]){	// elements ever meet
			if(pos_final[a]>pos_final[b])
				swap(a,b);
			Rv[a].PB( reaction(a, b, pos_final[b]-pos_final[a], i) );
		}
	}
	
	REP(i,n){
		sort(ALL(Rv[i]), reaction_greater);
	}
	REP(i,n){
		FOREACH(it,Rv[i]){
			R[i].PB(*it);
		}
	}

	lli result=0;
	REP(i,n){	// construct empty vials
		L[i].clear();
		L[i].PB(i);
	}
	priority_queue<reaction, vector<reaction>, reaction_prio> prioR;
	REP(i,m){	// simulate merging vials
		int a = seq[i].first;
		int b = seq[i].second;
		int size_a = L[a].size();
		int size_b = L[b].size();
		L[b].splice(L[b].begin(),L[a]);
		while(!R[a].empty() && R[a].back().dist < size_a + size_b){
			prioR.push(R[a].back());
			R[a].pop_back();
		}
		while(!prioR.empty()){
			int x = prioR.top().a;
			int y = prioR.top().b;
			prioR.pop();
			int s = min(g[x],g[y]);
			g[x]-=s;
			g[y]-=s;
			result += 2*s;
		}
		FOREACH(it,R[b]){
			it->dist += size_a;
		}
		//R[b].merge(R[a]);
		R[b].merge(R[a], reaction_greater);
	}
	
	printf("%lld\n", result);
	return 0;
}

/*
Niekoniecznie wszystkie substancje zostaną przelane do jednej fiolki, więc może pozostać kilka fiolek.

1. Potrzebujemy ustalić kolejność substancji we fiolkach na końcu. Najłatwiej chyba budować fiolki wg przepisu za pomocą list, i na końcu przelecieć listy i obliczyć dla każdej substancji pozycję na liście. Przyjmijmy, że przelewany bez odwracania - czyli zlewając jedną fiolkę do drugiej, to co było na górze pierwszej fiolki nadal jest na górze.

2. Pary reakcji mają już na wejściu ustaloną kolejność. Żeby szybko ich używać, zapiszmy każdą reakcję na liście dowiązanej do jednego z elementów którego dotyczy.
- jeżeli dwa elementy nigdy się nie spotkają, to taką reakcję oczywiście pomijamy
- wpp, przypisujemy reakcję do tego elementu, który jest w wynikowej fiolce WYŻEJ i jednocześnie zapisujemy jaka jest odległość między elementami w tej fiolce - będzie to potrzebne do obliczenia, w którym momencie reakcja może zostać użyta.

3. Każda substancja ma teraz swoją listę reakcji. Sortujemy każdą listę wg odległości do drugiego reagenta, rosnąco.

4. Teraz symulujemy zlewanie od początku. 
- A) Kiedy zlewamy jedną fiolkę do drugiej, to bierzemy listę reakcji ze szczytu pierwszej fiolki i ściągamy z jej początku te reakcje, które musimy wykonać. Ponieważ przypisywaliśmy reakcje do tego elementu z pary, który jest wyżej, to wiadomo że wszystkie reakcje które musimy wykonać są właśnie na szczycie pierwszej fiolki. Aby to zrobić, po prostu patrzymy jaką długość ma druga fiolka, i ściągamy z początku listy dopóki odległości są mniejsze (tak mamy posortowane reakcje). Ściągnięte reakcje wkładamy do priority_queue gdzie kluczem jest ich oryginalny priorytet i w końcu wykonujemy.
- B) Następnie bierzemy listę reakcji ze szczytu drugiej fiolki i scalamy z tym co pozostało na liście pierwszej fiolki (scalanie posortowanych list). Przed scaleniem musimy oczywiście poprawić odległości na liście z drugiej fiolki, bo przesuwamy jej punk odniesienia.

Zauważmy, że po zlaniu mamy zawsze jedną listę przypisaną do jednej fiolki.

Złożoność - chyba O(k + m*lgk + k*lgk + m*k), niestety scalanie posortowanych list moze wyjsc kwadratowe ;/
*/
