#include <bits/stdc++.h>
struct MI {
 private:
  char bb[1 << 14];
  FILE* f;
  char *bs, *be;
  char e;
  bool o, l;

 public:
  MI() : f(stdin), bs(0), be(0) {}
  inline char get() {
    if (o) {
      o = 0;
      return e;
    }
    if (bs == be) be = (bs = bb) + fread(bb, 1, sizeof(bb), f);
    if (bs == be) {
      l = 1;
      return -1;
    };
    return *bs++;
  }
  inline void unget(char c) {
    o = 1;
    e = c;
  }
  template <class T>
  inline T read() {
    T r;
    *this > r;
    return r;
  }
  template <class T>
  inline MI& operator>(T&);
};
template <class T>
struct Q {
  const static bool U = T(-1) >= T(0);
  inline void operator()(MI& t, T& r) const {
    r = 0;
    char c;
    bool y = 0;
    if (U)
      for (;;) {
        c = t.get();
        if (c == -1) goto E;
        if (isdigit(c)) break;
      }
    else
      for (;;) {
        c = t.get();
        if (c == -1) goto E;
        if (c == '-') {
          c = t.get();
          if (isdigit(c)) {
            y = 1;
            break;
          };
        } else if (isdigit(c))
          break;
        ;
      };
    for (;;) {
      if (c == -1) goto E;
      if (isdigit(c))
        r = r * 10 + (c ^ 48);
      else
        break;
      c = t.get();
    }
    t.unget(c);
  E:;
    if (y) r = -r;
  }
};
template <>
struct Q<char> {};
template <class T>
inline MI& MI::operator>(T& t) {
  Q<T>()(*this, t);
  return *this;
}
template <class T>
std::ostream& operator<(std::ostream& out, const T& t) {
  return out << t;
}
using std::cout;
MI cin;
const int $n = 1000005;
const int $m = 500005;
int n, m, k, v[$n], et, grp[$n], vis[$n * 2];
std::vector<int> outs[$n], ro[$n * 2];
struct edge {
  int x, y;
} es[$m];
bool col[$n], no[$n];
std::map<std::pair<int, int>, std::vector<int>> rep;
std::set<int> w;
bool dfs(int x) {
  grp[x] = grp[0];
  for (int v : outs[x]) {
    if (grp[v]) {
      if (col[v] == col[x]) return 1;
    } else {
      col[v] = col[x] ^ 1;
      if (dfs(v)) return 1;
    }
  }
  return 0;
}
bool load(int x) {
  static bool col[$n * 2];
  vis[x] = vis[0];
  for (int v : ro[x]) {
    if (vis[v] == vis[0]) {
      if (col[v] == col[x]) return 1;
    } else {
      col[v] = col[x] ^ 1;
      if (load(v)) return 1;
    }
  }
  return 0;
}
int main() {
  cin > n > m > k;
  for (int i = 1; i <= n; ++i) cin > v[i];
  for (int i = 0; i < m; ++i) {
    const int x = (cin.read<int>()), y = (cin.read<int>());
    if (v[x] == v[y])
      outs[x].push_back(y), outs[y].push_back(x);
    else
      es[++et] = {x, y};
  }
  long long ans = (long long)k * (k - 1) / 2;
  int rem = k;
  for (int i = 1; i <= n; ++i) {
    if (grp[i]) continue;
    ++grp[0];
    if (dfs(i)) {
      if (!no[v[i]]) {
        no[v[i]] = 1;
        ans -= --rem;
      }
    }
  }
  const int top = grp[0];
  for (int i = 1; i <= et; ++i) {
    auto [x, y] = es[i];
    if (no[v[x]] || no[v[y]]) continue;
    std::pair<int, int> key = {v[x], v[y]};
    if (key.first > key.second) std::swap(key.first, key.second);
    rep[key].push_back(i);
  }
  for (const auto& [pa, all] : rep) {
    const int A = pa.first, B = pa.second;
    auto add = [top](int x, int y) {
      const int xx = x > top ? x - top : x, yy = y > top ? y - top : y;
      if (w.insert(xx).second)
        ro[xx].clear(), ro[xx + top].clear(), ro[xx].push_back(xx + top),
            ro[xx + top].push_back(xx);
      if (w.insert(yy).second)
        ro[yy].clear(), ro[yy + top].clear(), ro[yy].push_back(yy + top),
            ro[yy + top].push_back(yy);
      ro[x].push_back(y);
      ro[y].push_back(x);
    };
    w.clear();
    for (int id : all) {
      auto [x, y] = es[id];
      if (col[x] == col[y]) {
        add(grp[x], grp[y] + top);
        add(grp[y], grp[x] + top);
      } else {
        add(grp[x], grp[y]);
        add(grp[x] + top, grp[y] + top);
      }
    }
    ++vis[0];
    bool ok = 1;
    for (int v : w)
      if (vis[v] != vis[0] && load(v)) {
        ok = 0;
        break;
      }
    if (!ok) --ans;
  }
  cout < ans < ('\n');
}
