#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll solve(int n, int m, int k, vector<int> &c, vector<pair<int, int>> &edges) {
  using Graph = map<int, vector<int>>;
  map<int, map<int, Graph>> g;
  vector<pair<int, int>> group_pairs;
  for (auto &[u, v] : edges) {
    if (c[u] > c[v]) swap(u, v);
    if (c[u] != c[v]) {
      group_pairs.emplace_back(c[u], c[v]);
    } else {
      g[c[u]][c[v]][u].push_back(v);
      g[c[u]][c[v]][v].push_back(u);
    }
  }
  sort(group_pairs.begin(), group_pairs.end());
  group_pairs.erase(unique(group_pairs.begin(), group_pairs.end()),
                    group_pairs.end());
  struct DSU {
    int n;
    vector<int> p;
    DSU(int n) : n(n), p(n) { iota(p.begin(), p.end(), 0); }
    int getp(int v) {
      if (v == p[v]) return v;
      return p[v] = getp(p[v]);
    }
    bool unite(int u, int v) {
      u = getp(u);
      v = getp(v);
      if (u == v) return false;
      p[u] = v;
      return true;
    }
  };
  vector<int> same_group_color(n + 1);
  vector<int> component_inversed(n + 1);
  vector<int> component_used(n + 1);
  vector<int> used(3 * (n + 1));
  DSU same_group_dsu(n + 1);
  function<bool(Graph &, int, int)> dfs1 = [&](Graph &g, int v, int c) {
    used[v] = true;
    same_group_color[v] = c;
    for (auto to : g[v]) {
      if (!used[to]) {
        same_group_dsu.unite(v, to);
        if (!dfs1(g, to, !c)) {
          return false;
        }
      } else if (same_group_color[to] == c) {
        return false;
      }
    }
    return true;
  };
  ll res = 1LL * k * (k - 1) / 2;
  vector<int> bad_group(k + 1);
  int bad_groups_cnt = 0;
  for (int i = 1; i <= k; ++i) {
    auto &gg = g[i][i];
    for (auto &[x, vec] : gg) {
      if (!used[x] && !dfs1(gg, x, 0)) {
        bad_group[i] = true;
        bad_groups_cnt++;
        res -= (k - bad_groups_cnt);
        break;
      }
    }
  }
  vector<int> double_group(n + 1);
  for (int i = 1; i <= n; ++i) {
    if (same_group_color[i]) {
      int group = same_group_dsu.getp(i);
      double_group[group] = true;
    }
  }
  set<tuple<int, int, int>> double_group_used;
  for (auto [u, v] : edges) {
    int cu = c[u];
    int cv = c[v];
    if (!bad_group[cu] && !bad_group[cv]) {
      int gru = same_group_dsu.getp(u);
      int grv = same_group_dsu.getp(v);
      int uu = 2 * gru + same_group_color[u];
      int vv = 2 * grv + same_group_color[v];
      if (double_group[gru] && !double_group_used.count({cu, cv, gru})) {
        g[cu][cv][2 * gru].push_back(2 * gru + 1);
        g[cu][cv][2 * gru + 1].push_back(2 * gru);
        double_group_used.emplace(cu, cv, gru);
      }
      if (double_group[grv] && !double_group_used.count({cu, cv, grv})) {
        g[cu][cv][2 * grv].push_back(2 * grv + 1);
        g[cu][cv][2 * grv + 1].push_back(2 * grv);
        double_group_used.emplace(cu, cv, grv);
      }
      g[c[u]][c[v]][uu].push_back(vv);
      g[c[u]][c[v]][vv].push_back(uu);
    }
  }
  int timer = 1;
  vector<int> color(3 * (n + 1));
  function<bool(Graph &, int, int)> dfs = [&](Graph &g, int v, int c) {
    if (used[v] == timer) return color[v] == c;
    used[v] = timer;
    color[v] = c;
    for (auto to : g[v]) {
      if (!dfs(g, to, !c)) {
        return false;
      }
    }
    return true;
  };
  for (auto [cu, cv] : group_pairs) {
    ++timer;
    if (bad_group[cu] || bad_group[cv]) {
      continue;
    }
    auto &gg = g[cu][cv];
    for (auto &[x, vec] : gg) {
      if (used[x] != timer && !dfs(gg, x, 0)) {
        --res;
        break;
      }
    }
  }
  return res;
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m, k;
  while (cin >> n >> m >> k) {
    vector<int> c(n + 1);
    for (int i = 1; i <= n; ++i) cin >> c[i];
    vector<pair<int, int>> edges;
    for (int i = 0; i < m; ++i) {
      int u, v;
      cin >> u >> v;
      edges.emplace_back(u, v);
    }
    auto res = solve(n, m, k, c, edges);
    cout << res << "\n";
  }
}
