#include <bits/stdc++.h>
using namespace std;
template <class T1, class T2>
ostream &operator<<(ostream &out, const pair<T1, T2> p) {
  out << '(' << p.first << ',' << p.second << ')';
  return out;
}
template <class T1, class T2>
istream &operator>>(istream &in, pair<T1, T2> &p) {
  in >> p.first >> p.second;
  return in;
}
template <class T>
istream &operator>>(istream &in, vector<T> &v) {
  for (T &x : v) in >> x;
  return in;
}
template <class T>
ostream &operator<<(ostream &out, const vector<vector<T>> &v) {
  for (const vector<T> &x : v) out << x << '\n';
  return out;
}
template <class T>
ostream &operator<<(ostream &out, const vector<T> &v) {
  for (const T &x : v) out << x << ' ';
  return out;
}
long long gcd(long long a, long long b) {
  if (b > a) swap(a, b);
  return (b ? gcd(b, a % b) : a);
}
using ll = long long;
using pii = pair<int, int>;
using pll = pair<long long, long long>;
using tiii = pair<pair<int, int>, int>;
using vi = vector<int>;
using vl = vector<long long>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<long long>>;
const int h = 1000000007;
vvi cols, d_g;
class Graph {
 private:
  const vector<vector<pair<int, long long>>> adj;
  const vector<vector<pair<int, long long>>> get_weighted_adj(
      const vector<vector<int>> &unweighted_adj) const {
    vector<vector<pair<int, long long>>> weighted_adj(unweighted_adj.size());
    for (int i = 0; i < unweighted_adj.size(); i++) {
      for (int j = 0; j < unweighted_adj[i].size(); j++) {
        weighted_adj[i].push_back({unweighted_adj[i][j], 1LL});
      }
    }
    return weighted_adj;
  }

 public:
  Graph(const vector<vector<pair<int, long long>>> &_adj) : adj(_adj) {}
  Graph(const vector<vector<int>> &_adj) : adj(get_weighted_adj(_adj)) {}
  bool is_bipartite(int I) const {
    vector<bool> vis(adj.size()), col(adj.size());
    stack<int> st;
    for (int i = 0; i < adj.size(); i++) {
      if (vis[i]) continue;
      vis[i] = true;
      st.push(i);
      while (!st.empty()) {
        const int x = st.top();
        if (I != -1) d_g[I][x] = i;
        st.pop();
        for (const pair<int, long long> &p : adj[x]) {
          if (vis[p.first]) {
            if (col[p.first] == col[x]) return false;
            continue;
          }
          col[p.first] = !col[x];
          if (I != -1) cols[I][p.first] = !col[x];
          vis[p.first] = true;
          st.push(p.first);
        }
      }
    }
    return true;
  }
  long long distance(const int source, const int destination) const {
    vector<bool> vis(adj.size());
    priority_queue<pair<int, long long>, vector<pair<int, long long>>,
                   greater<pair<int, long long>>>
        pq;
    pq.push({0, source});
    while (!pq.empty()) {
      const long long w = pq.top().first;
      const int x = pq.top().second;
      pq.pop();
      if (x == destination) return w;
      if (vis[x]) continue;
      vis[x] = true;
      for (const pair<int, long long> &p : adj[x])
        pq.push({w + p.second, p.first});
    }
    return numeric_limits<long long>::max();
  }
};
signed main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cerr.setstate(ios::failbit);
  int n, m, k;
  cin >> n >> m >> k;
  vi c(n);
  cin >> c;
  for (auto &x : c) x--;
  vector<pii> vp(m);
  for (int i = (0); i < (m); i++) {
    int x, y;
    cin >> x >> y;
    x--, y--;
    vp[i] = {x, y};
  }
  vi p(k), in(n, -1);
  for (auto x : vp) {
    if (in[x.first] == -1) in[x.first] = p[c[x.first]]++;
    if (in[x.second] == -1) in[x.second] = p[c[x.second]]++;
  }
  vector<vvi> g(k);
  for (int i = (0); i < (k); i++) g[i].resize(p[i]);
  for (int i = (0); i < (m); i++) {
    int x = vp[i].first, y = vp[i].second;
    if (c[x] == c[y]) {
      g[c[x]][in[x]].push_back(in[y]);
      g[c[x]][in[y]].push_back(in[x]);
    }
  }
  vi b(k);
  cols.resize(k);
  d_g.resize(k);
  for (int i = (0); i < (k); i++) {
    cols[i].resize(p[i]);
    d_g[i].resize(p[i]);
    b[i] = Graph(g[i]).is_bipartite(i);
  }
  ll bc = k - count(b.begin(), b.end(), 0);
  ll ans = bc * (bc - 1) / 2;
  map<pii, int> e_to_num;
  map<pii, map<pii, int>> M;
  vector<vvi> FG;
  for (int i = (0); i < (m); i++) {
    int x = vp[i].first, y = vp[i].second;
    if (c[x] != c[y] and b[c[x]] and b[c[y]]) {
      if (c[x] > c[y]) swap(x, y);
      if (!e_to_num.count(make_pair(c[x], c[y]))) {
        int sz = e_to_num.size();
        e_to_num[make_pair(c[x], c[y])] = sz;
        FG.resize(e_to_num.size());
      }
      int &en = e_to_num[make_pair(c[x], c[y])];
      auto &Mv = M[make_pair(c[x], c[y])];
      auto dx = make_pair(c[x], d_g[c[x]][in[x]]);
      auto dy = make_pair(c[y], d_g[c[y]][in[y]]);
      if (!Mv.count(dx)) {
        int sz = Mv.size();
        Mv[dx] = sz;
        FG[en].resize(2 * Mv.size());
        FG[en][2 * Mv.size() - 2].push_back(2 * Mv.size() - 1);
        FG[en][2 * Mv.size() - 1].push_back(2 * Mv.size() - 2);
      }
      if (!Mv.count(make_pair(c[y], d_g[c[y]][in[y]]))) {
        int sz = Mv.size();
        Mv[dy] = sz;
        FG[en].resize(2 * Mv.size());
        FG[en][2 * Mv.size() - 2].push_back(2 * Mv.size() - 1);
        FG[en][2 * Mv.size() - 1].push_back(2 * Mv.size() - 2);
      }
      int cx = cols[c[x]][in[x]];
      int cy = cols[c[y]][in[y]];
      FG[en][2 * Mv[dx] + cx].push_back(2 * Mv[dy] + cy);
      FG[en][2 * Mv[dy] + cy].push_back(2 * Mv[dx] + cx);
    }
  }
  vi fb(FG.size());
  for (int i = (0); i < (FG.size()); i++) {
    fb[i] = Graph(FG[i]).is_bipartite(-1);
    if (!fb[i]) ans--;
  }
  cout << ans;
}
