#include <bits/stdc++.h>
using namespace std;
const int MX = 500000;
int c[MX];
int edges[MX][2];
bool bipartite[MX];
bool part[MX];
int parent[MX];
vector<int> lst[MX];
stack<pair<int, int>> changes;
unordered_map<string, vector<int>> colors_edges;
unordered_set<string> bad_pairs;
void make_set(int u) {
  lst[u].push_back(u);
  parent[u] = u;
  part[u] = false;
}
int find_set(int u) { return parent[u]; }
bool unite(int u, int v, bool save) {
  bool invert = part[u] == part[v];
  u = find_set(u);
  v = find_set(v);
  if (u == v) return !invert;
  if (lst[u].size() > lst[v].size()) {
    int temp = u;
    u = v;
    v = temp;
  }
  if (save) changes.push({u, v});
  for (int x : lst[u]) {
    parent[x] = v;
    lst[v].push_back(x);
    part[x] = part[x] ^ invert;
  }
  return true;
}
void undo(pair<int, int> change) {
  for (int x : lst[change.first]) {
    parent[x] = change.first;
    lst[change.second].pop_back();
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n, m, k;
  cin >> n >> m >> k;
  for (int i = 0; i < n; i++) {
    cin >> c[i];
    c[i]--;
  }
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    if (c[u] > c[v]) {
      int temp = u;
      u = v;
      v = temp;
    }
    edges[i][0] = u;
    edges[i][1] = v;
  }
  for (int i = 0; i < k; i++) bipartite[i] = true;
  for (int u = 0; u < n; u++) make_set(u);
  for (int i = 0; i < m; i++) {
    int u = edges[i][0];
    int v = edges[i][1];
    if (c[u] == c[v]) {
      bipartite[c[u]] = bipartite[c[u]] && unite(u, v, false);
    } else {
      string key = to_string(c[u]) + " " + to_string(c[v]);
      if (colors_edges.find(key) == colors_edges.end())
        colors_edges[key] = vector<int>();
      colors_edges[key].push_back(i);
    }
  }
  long long bipartite_cnt = 0L;
  for (int i = 0; i < k; i++)
    if (bipartite[i]) bipartite_cnt++;
  long long ans = (bipartite_cnt * (bipartite_cnt - 1LL)) / 2LL;
  for (auto &it : colors_edges) {
    string key = it.first;
    int t = key.length();
    int div = key.find(" ");
    string s0 = key.substr(0, div);
    string s1 = key.substr(div + 1, t - s0.length());
    int c0 = stoi(s0);
    int c1 = stoi(s1);
    if (!bipartite[c0] || !bipartite[c1] || it.second.size() <= 1) continue;
    for (int i : it.second) {
      int u = edges[i][0];
      int v = edges[i][1];
      if (!unite(u, v, true)) {
        bad_pairs.insert(key);
        break;
      }
    }
    while (!changes.empty()) {
      undo(changes.top());
      changes.pop();
    }
  }
  cout << (ans - bad_pairs.size());
  return 0;
}
