#include <bits/stdc++.h>
using namespace std;
template <class T, class V>
ostream &operator<<(ostream &s, pair<T, V> a) {
  s << a.first << ' ' << a.second;
  return s;
}
struct dsu_save {
  int v, rnkv, u, rnku, united, valv, valu;
  dsu_save() {}
  dsu_save(int _v, int _rnkv, int _u, int _rnku, int united, int _vv, int _vu)
      : v(_v),
        rnkv(_rnkv),
        u(_u),
        rnku(_rnku),
        united(united),
        valv(_vv),
        valu(_vu) {}
};
class Unionfind {
 public:
  vector<long long int> p, rnk, val;
  vector<dsu_save> lastadded;
  Unionfind(int N) {
    val.assign(N, 0);
    p.assign(N, 0);
    rnk.assign(N, 1);
    for (int i = 0; i < N; i++) p[i] = i;
  }
  int findset(int i, int &t) {
    return t += val[i], (p[i] == i) ? i : findset(p[i], t);
  }
  bool unionset(int i, int j) {
    int a = 0, b = 0;
    int x = findset(i, a);
    int y = findset(j, b);
    if (x != y) {
      if (rnk[x] > rnk[y])
        lastadded.emplace_back(y, rnk[y], x, rnk[x], 1, val[y], val[x]),
            p[y] = x, val[y] = 1 + (a % 2 != b % 2);
      else {
        lastadded.emplace_back(x, rnk[x], y, rnk[y], 1, val[x], val[y]);
        p[x] = y;
        if (rnk[x] == rnk[y]) rnk[y]++;
        val[x] = 1 + (a % 2 != b % 2);
      }
    } else
      return lastadded.emplace_back(x, rnk[x], y, rnk[y], 0, val[x], val[y]),
             a % 2 != b % 2;
    return true;
  }
  void rollback() {
    if (lastadded.empty()) return;
    auto x = lastadded.back();
    lastadded.pop_back();
    if (x.united == 0) return;
    p[x.v] = x.v;
    p[x.u] = x.u;
    rnk[x.v] = x.rnkv;
    rnk[x.u] = x.rnku;
    val[x.v] = x.valv;
    val[x.u] = x.valu;
  }
};
vector<long long int> adj[500005];
int main() {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  int T = 1;
  for (int qq = 1; qq <= T; qq++) {
    int n, k, m;
    cin >> n >> m >> k;
    vector<long long int> v(n), ok(k);
    vector<vector<long long int> > a(k);
    for (int i = 0; i < n; i++) {
      cin >> v[i];
      a[--v[i]].push_back(i);
    }
    for (int i = 0; i < m; i++) {
      int p, q;
      cin >> p >> q;
      adj[--p].push_back(--q);
      adj[q].push_back(p);
    }
    Unionfind un(n);
    long long int ans = k;
    for (int i = 0; i < k; i++) {
      int u = 0, p = 0;
      for (auto x : a[i]) {
        for (auto y : adj[x])
          if (v[y] == i && ++u && !un.unionset(x, y)) p = 1;
      }
      if (p) {
        while (u--) un.rollback();
      }
      ok[i] = p;
      ans -= p;
    }
    ans = ans * (ans - 1) / 2;
    for (int i = 1; i < k; i++) {
      if (ok[i]) continue;
      vector<pair<long long int, long long int> > temp;
      for (auto x : a[i]) {
        for (auto y : adj[x])
          if (!ok[v[y]] && v[y] < i)
            temp.push_back(pair<long long int, long long int>(x, y));
      }
      sort(temp.begin(), temp.end(),
           [&](pair<long long int, long long int> a,
               pair<long long int, long long int> b) {
             return v[a.second] < v[b.second];
           });
      int last = -1, u = 0, p = 0;
      for (auto x : temp) {
        if (v[x.second] != last) {
          last = v[x.second];
          while (u != 0) un.rollback(), u--;
          p = 0;
        }
        if (!un.unionset(x.first, x.second) && !p) p = 1, ans--;
        u++;
      }
      while (u--) un.rollback();
    }
    cout << ans << endl;
  }
}
