#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 100;
map<pair<int, int>, vector<pair<int, int>>> mp;
struct revo {
  int fax, fay;
  int rkx, rky;
};
int a[N], b[N], f[N], rk[N], type[N], tot;
bool fail[N];
stack<revo> st;
int find(int x) { return f[x] == x ? x : find(f[x]); }
void merge(int x, int y) {
  int xx = find(x), yy = find(y);
  revo temp;
  temp.fax = xx, temp.fay = yy;
  temp.rkx = rk[xx], temp.rky = rk[yy];
  st.push(temp);
  if (rk[xx] > rk[yy]) swap(xx, yy);
  f[xx] = yy;
  rk[yy] = max(rk[yy], rk[xx] + 1);
}
void revocation(int k) {
  while (k--) {
    revo node = st.top();
    st.pop();
    f[node.fax] = node.fax;
    f[node.fay] = node.fay;
    rk[node.fax] = node.rkx;
    rk[node.fay] = node.rky;
  }
}
void init() {
  for (int i = 1; i < N; i++) {
    f[i] = i;
    rk[i] = 1;
  }
}
int main() {
  init();
  int n, m, k;
  long long ans = 0;
  scanf("%d%d%d", &n, &m, &k);
  for (int i = 1; i <= n; i++) scanf("%d", type + i);
  for (int i = 1; i <= m; i++) scanf("%d%d", a + i, b + i);
  for (int i = 1; i <= m; i++) {
    if (type[a[i]] == type[b[i]]) {
      int xx = find(a[i]), yy = find(b[i]);
      if (xx != yy)
        merge(a[i], b[i] + n), merge(b[i], a[i] + n);
      else
        fail[type[a[i]]] = true;
    }
  }
  for (int i = 1; i <= m; i++) {
    if (type[a[i]] == type[b[i]]) continue;
    if (fail[type[a[i]]] || fail[type[b[i]]]) continue;
    if (type[a[i]] > type[b[i]]) swap(a[i], b[i]);
    mp[make_pair(type[a[i]], type[b[i]])].emplace_back(a[i], b[i]);
  }
  for (auto node : mp) {
    int cnt = 0;
    for (auto it : node.second) {
      int x, y;
      tie(x, y) = it;
      int xx = find(x), yy = find(y);
      if (xx != yy)
        merge(x, y + n), merge(y, x + n), cnt += 2;
      else {
        ans--;
        break;
      }
    }
    revocation(cnt);
  }
  long long cnt = 0;
  for (int i = 1; i <= k; i++)
    if (!fail[i]) cnt++;
  ans += cnt * (cnt - 1) / 2;
  printf("%lld\n", ans);
  return 0;
}
