#include <bits/stdc++.h>
using namespace std;
vector<int, int> &getVector(const unordered_map<long long, int> &trad,
                            vector<map<int, int>> &g, int dst, int &prox,
                            long long res, int v, int i);
template <class C>
void mini(C &a, C b) {
  a = min(a, b);
}
template <class C>
void maxi(C &a, C b) {
  a = max(a, b);
}
struct persistentDSU {
  persistentDSU(int n) {
    p.resize(n);
    for (int i = 0; i < n; i++) p[i] = i;
    s = vector<int>(n, 1);
    stack = {{}};
    c = vector<int>(n);
  }
  int find(int u) {
    while (u != p[u]) u = p[u];
    return u;
  }
  int color(int u) {
    int res = 0;
    while (u != p[u]) {
      res++;
      res += c[u];
      u = p[u];
    }
    return res % 2;
  }
  bool unite(int u, int v) {
    int a = u;
    int b = v;
    u = find(u);
    v = find(v);
    if (u == v) return color(a) != color(b);
    if (s[u] < s[v]) swap(u, v);
    if (color(a) != color(b))
      stack.back().emplace_back(make_tuple(u, v, 1));
    else
      stack.back().emplace_back(make_tuple(u, v, 0));
    if (color(a) != color(b)) c[v]++;
    p[v] = u;
    s[u] += s[v];
    return true;
  }
  void persist() { stack.emplace_back(vector<tuple<int, int, int>>()); }
  void rollback() {
    while (!stack.back().empty()) {
      int u, v, si;
      tie(u, v, si) = stack.back().back();
      p[v] = v;
      s[u] -= s[v];
      c[v] -= si;
      stack.back().pop_back();
    }
    stack.pop_back();
  }
  vector<int> p;
  vector<int> s;
  vector<int> c;
  vector<vector<tuple<int, int, int>>> stack;
};
vector<int> a;
bool cmp(pair<int, int> e1, pair<int, int> e2) {
  if (a[e1.first] != a[e2.first]) return a[e1.first] < a[e2.first];
  return a[e1.second] < a[e2.second];
}
void c() {
  int n, m, k, u, v;
  cin >> n >> m >> k;
  a.resize(n);
  for (int i = 0; i < n; i++) cin >> a[i];
  for (int i = 0; i < n; i++) a[i]--;
  vector<bool> bipartito(k, true);
  vector<int> trad(n);
  vector<int> saiz(k);
  for (int i = 0; i < n; i++) {
    trad[i] = saiz[a[i]];
    saiz[a[i]]++;
  }
  vector<persistentDSU> uf;
  for (int i = 0; i < k; i++) uf.emplace_back(persistentDSU(saiz[i]));
  vector<pair<int, int>> E(m);
  for (int i = 0; i < m; i++) cin >> E[i].first >> E[i].second;
  for (int i = 0; i < m; i++) E[i].first--;
  for (int i = 0; i < m; i++) E[i].second--;
  for (int i = 0; i < m; i++)
    if (a[E[i].first] > a[E[i].second]) swap(E[i].first, E[i].second);
  sort(E.begin(), E.end(), cmp);
  persistentDSU total(n);
  for (auto e : E) {
    if (a[e.first] != a[e.second]) continue;
    int group = a[e.first];
    tie(u, v) = e;
    u = trad[u];
    v = trad[v];
    bipartito[group] = bipartito[group] and uf[group].unite(u, v);
  }
  for (auto e : E) {
    if (a[e.first] != a[e.second]) continue;
    int group = a[e.first];
    if (!bipartito[group]) continue;
    tie(u, v) = e;
    total.unite(u, v);
  }
  long long res = 0;
  for (int i = 0; i < k; i++)
    if (bipartito[i]) res++;
  res = res * (res - 1) / 2;
  int i = 0;
  while (i < m) {
    int j = i;
    while (j < m and a[E[j].first] == a[E[i].first] and
           a[E[j].second] == a[E[i].second])
      j++;
    int g1 = a[E[i].first];
    int g2 = a[E[i].second];
    if (g1 != g2 and bipartito[g1] and bipartito[g2]) {
      total.persist();
      for (int ii = i; ii <= j - 1; ii++) {
        tie(u, v) = E[ii];
        if (!total.unite(u, v)) {
          res--;
          break;
        }
      }
      total.rollback();
    }
    i = j;
  }
  cout << res << '\n';
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  c();
  return 0;
}
