#include <bits/stdc++.h>
using namespace std;
int n, m, k;
int a[(int)(1e6 + 10)], b[(int)(1e6 + 10)];
int c[(int)(1e6 + 10)];
int p[(int)(1e6 + 10)];
int rk[(int)(1e6 + 10)];
bool color[(int)(1e6 + 10)];
int find(int x) { return p[x] == x ? x : find(p[x]); }
void init() {
  for (int i = 1; i <= 1e6; i++) p[i] = i, rk[i] = 1;
}
struct revo {
  int px, py, rkx, rky;
};
stack<revo> st;
void merge(int x, int y) {
  int px = find(x), py = find(y);
  revo tmp = {px, py, rk[px], rk[py]};
  st.push(tmp);
  if (rk[px] > rk[py]) swap(px, py);
  p[px] = py;
  rk[py] = max(rk[py], rk[px] + 1);
}
void revocation(int k) {
  while (k--) {
    revo node = st.top();
    st.pop();
    p[node.px] = node.px;
    p[node.py] = node.py;
    rk[node.px] = node.rkx;
    rk[node.py] = node.rky;
  }
}
map<pair<int, int>, vector<pair<int, int> > > mp;
long long ans;
int main() {
  ios::sync_with_stdio(0);
  init();
  cin >> n >> m >> k;
  for (int i = 1; i <= n; i++) cin >> c[i];
  for (int i = 1; i <= m; i++) cin >> a[i] >> b[i];
  for (int i = 1; i <= m; i++) {
    if (c[a[i]] == c[b[i]]) {
      int x = find(a[i]), y = find(b[i]);
      if (x != y)
        merge(a[i], b[i] + n), merge(b[i], a[i] + n);
      else
        color[c[a[i]]] = 1;
    }
  }
  for (int i = 1; i <= m; i++) {
    if (c[a[i]] == c[b[i]]) continue;
    if (color[c[a[i]]] || color[c[b[i]]]) continue;
    if (c[a[i]] > c[b[i]]) swap(a[i], b[i]);
    mp[{c[a[i]], c[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 px = find(x), py = find(y);
      if (px != py)
        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 (!color[i]) cnt++;
  ans += cnt * (cnt - 1) / 2;
  cout << ans << endl;
}
