#include <bits/stdc++.h>
namespace atcoder {
struct dsu {
 public:
  dsu() : _n(0) {}
  dsu(int n) : _n(n), parent_or_size(n, -1) {}
  int merge(int a, int b) {
    assert(0 <= a && a < _n);
    assert(0 <= b && b < _n);
    int x = leader(a), y = leader(b);
    if (x == y) return x;
    if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
    parent_or_size[x] += parent_or_size[y];
    parent_or_size[y] = x;
    return x;
  }
  bool same(int a, int b) {
    assert(0 <= a && a < _n);
    assert(0 <= b && b < _n);
    return leader(a) == leader(b);
  }
  int leader(int a) {
    assert(0 <= a && a < _n);
    if (parent_or_size[a] < 0) return a;
    return parent_or_size[a] = leader(parent_or_size[a]);
  }
  int size(int a) {
    assert(0 <= a && a < _n);
    return -parent_or_size[leader(a)];
  }
  std::vector<std::vector<int>> groups() {
    std::vector<int> leader_buf(_n), group_size(_n);
    for (int i = 0; i < _n; i++) {
      leader_buf[i] = leader(i);
      group_size[leader_buf[i]]++;
    }
    std::vector<std::vector<int>> result(_n);
    for (int i = 0; i < _n; i++) {
      result[i].reserve(group_size[i]);
    }
    for (int i = 0; i < _n; i++) {
      result[leader_buf[i]].push_back(i);
    }
    result.erase(
        std::remove_if(result.begin(), result.end(),
                       [&](const std::vector<int> &v) { return v.empty(); }),
        result.end());
    return result;
  }

 private:
  int _n;
  std::vector<int> parent_or_size;
};
}  // namespace atcoder
using namespace std;
using namespace atcoder;
using ll = long long;
template <class t, class u>
bool chmax(t &a, u b) {
  if (a < b) a = b;
  return a < b;
}
template <class t, class u>
bool chmin(t &a, u b) {
  if (b < a) a = b;
  return b < a;
}
template <class t>
using vc = vector<t>;
template <class t>
using vvc = vector<vector<t>>;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using vi = vc<int>;
using vl = vc<ll>;
ll readl(void) {
  ll x;
  cin >> x;
  return x;
}
int readi(void) {
  int x;
  cin >> x;
  return x;
}
string readstr() {
  string s;
  cin >> s;
  return s;
}
vi readvi(int n, int off = 0) {
  vi v(n);
  for (int i = int(0); i < int(n); i++) v[i] = readi(), v[i] += off;
  return v;
}
vl readvl(int n, int off = 0) {
  vl v(n);
  for (int i = int(0); i < int(n); i++) v[i] = readl(), v[i] += off;
  return v;
}
template <class t>
void print(t x, int suc = 1) {
  cout << x;
  if (suc == 1) cout << "\n";
  if (suc == 2) cout << " ";
}
template <class t>
void print(const vc<t> &v, int suc = 1) {
  for (int i = int(0); i < int(int(v.size())); i++)
    print(v[i], i == int(int(v.size())) - 1 ? 1 : suc);
}
template <class t>
bool inc(t a, t b, t c) {
  return !(c < b || b < a);
}
template <class t>
void compress(vc<t> &v) {
  sort(v.begin(), v.end());
  v.erase(unique(v.begin(), v.end()), v.end());
}
template <class t>
int lwb(const vc<t> &v, const t &a) {
  return lower_bound(v.begin(), v.end(), a) - v.begin();
}
template <class t>
struct Compress {
  vc<t> v;
  Compress() = default;
  Compress(const vc<t> &x) { add(x); }
  Compress(const initializer_list<vc<t>> &x) {
    for (auto &p : x) add(p);
  }
  void add(const t &x) { v.emplace_back(x); }
  void add(const vc<t> &x) { copy(x.begin(), x.end(), back_inserter(v)); }
  void build() { compress(v); }
  int get(const t &x) const { return lwb(v, x); }
  vc<t> get(const vc<t> &x) const {
    vc<t> res(x);
    for (auto &p : res) p = get(p);
    return res;
  }
  const t &operator[](int x) const { return v[x]; }
  int size() { return v.size(); }
};
void Yes(bool ex = true) {
  cout << "Yes\n";
  if (ex) exit(0);
}
void YES(bool ex = true) {
  cout << "YES\n";
  if (ex) exit(0);
}
void No(bool ex = true) {
  cout << "No\n";
  if (ex) exit(0);
}
void NO(bool ex = true) {
  cout << "NO\n";
  if (ex) exit(0);
}
void orYes(bool x, bool ex = true) {
  if (x)
    Yes(ex);
  else
    No(ex);
}
void orYES(bool x, bool ex = true) {
  if (x)
    YES(ex);
  else
    NO(ex);
}
void Possible(bool ex = true) {
  cout << "Possible\n";
  if (ex) exit(0);
}
void POSSIBLE(bool ex = true) {
  cout << "POSSIBLE\n";
  if (ex) exit(0);
}
void Impossible(bool ex = true) {
  cout << "Impossible\n";
  if (ex) exit(0);
}
void IMPOSSIBLE(bool ex = true) {
  cout << "IMPOSSIBLE\n";
  if (ex) exit(0);
}
void orPossible(bool x, bool ex = true) {
  if (x)
    Possible(ex);
  else
    Impossible(ex);
}
void orPOSSIBLE(bool x, bool ex = true) {
  if (x)
    POSSIBLE(ex);
  else
    IMPOSSIBLE(ex);
}
using uint = unsigned;
using ull = unsigned long long;
template <uint const &MOD>
struct Modular {
  static constexpr uint const &mod = MOD;
  uint v;
  Modular(long long x = 0) { c(x % mod + mod); }
  Modular &c(uint x) {
    v = x < mod ? x : x - mod;
    return *this;
  }
  Modular pow(int k) const {
    Modular res(1), tmp(v);
    while (k) {
      if (k & 1) res *= tmp;
      tmp *= tmp;
      k >>= 1;
    }
    return res;
  }
  Modular inv() const { return pow(mod - 2); }
  Modular operator-() const { return Modular(mod - v); }
  Modular &operator+=(const Modular &x) { return c(v + x.v); }
  Modular &operator-=(const Modular &x) { return c(v + mod - x.v); }
  Modular &operator*=(const Modular &x) {
    v = ull(v) * x.v % mod;
    return *this;
  }
  Modular &operator/=(const Modular &x) { return *this *= x.inv(); }
  Modular operator+(const Modular &x) const { return Modular(*this) += x; }
  Modular operator-(const Modular &x) const { return Modular(*this) -= x; }
  Modular operator*(const Modular &x) const { return Modular(*this) *= x; }
  Modular operator/(const Modular &x) const { return Modular(*this) /= x; }
  friend Modular operator+(long long x, const Modular &y) {
    return Modular(x) + y;
  }
  friend Modular operator-(long long x, const Modular &y) {
    return Modular(x) - y;
  }
  friend Modular operator*(long long x, const Modular &y) {
    return Modular(x) * y;
  }
  friend Modular operator/(long long x, const Modular &y) {
    return Modular(x) / y;
  }
  friend ostream &operator<<(ostream &os, const Modular &x) {
    return os << x.v;
  }
  friend istream &operator>>(istream &is, Modular &x) {
    long long p;
    is >> p;
    x = Modular(p);
    return is;
  }
  bool operator==(const Modular &x) const { return v == x.v; }
  bool operator!=(const Modular &x) const { return v != x.v; }
  bool operator<(const Modular &x) const { return v < x.v; }
  explicit operator bool() const { return v; }
};
uint MODULAR = 998244353;
using Mint = Modular<MODULAR>;
vector<Mint> fact, finv, invs;
void Initfact(int n = (1 << 21) + 10) {
  fact.resize(n + 1), finv.resize(n + 1), invs.resize(n + 1);
  fact[0] = 1;
  for (int i = 1; i <= n; i++) {
    fact[i] = fact[i - 1] * i;
  }
  finv[n] = fact[n].inv();
  for (int i = n - 1; i >= 0; i--) {
    finv[i] = finv[i + 1] * (i + 1);
  }
  invs[0] = 1;
  for (int i = 0; i <= n; i++) {
    invs[i] = finv[i] * fact[i - 1];
  }
}
Mint comb(int n, int k) { return fact[n] * finv[n - k] * finv[k]; }
ll gcd(ll a, ll b) {
  if (a < b) swap(a, b);
  if (b == 0) return a;
  return gcd(b, a % b);
}
int n, m, k, c[500005], led[500005], r[500005], ir[500005];
map<pi, vc<pi>> e;
ll ans;
bool ok[500005];
vi g[500005];
void dfs(int v, int cc) {
  ir[v] = cc;
  for (auto &i : g[v]) {
    if (ir[i] == -1) {
      dfs(i, (cc + 1) % 2);
    }
  }
}
int main(void) {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cin >> n >> m >> k;
  for (int i = int(0); i < int(k); i++) ok[i] = true;
  for (int i = int(0); i < int(n); i++) {
    cin >> c[i];
    c[i]--;
  }
  dsu uf(n * 2);
  dsu uff(n);
  for (int i = int(0); i < int(m); i++) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    if (c[a] == c[b]) {
      uf.merge(a, b + n);
      uf.merge(b, a + n);
      uff.merge(a, b);
      g[a].push_back(b);
      g[b].push_back(a);
    } else {
      if (c[a] > c[b]) swap(a, b);
      e[make_pair(c[a], c[b])].push_back(make_pair(a, b));
    }
  }
  for (int i = int(0); i < int(n); i++) {
    ir[i] = -1;
  }
  for (int i = int(0); i < int(n); i++) {
    if (ir[i] == -1) {
      dfs(i, 0);
    }
  }
  for (int i = int(0); i < int(n); i++) {
    if (uf.same(i, i + n)) {
      ok[c[i]] = false;
    }
  }
  ll s = 0;
  for (int i = int(0); i < int(k); i++) {
    if (ok[i]) {
      ans += s;
      s++;
    }
  }
  for (int i = int(0); i < int(n); i++) r[i] = -1;
  for (auto &gg : e) {
    vc<pi> x = gg.second;
    if (!ok[c[x[0].first]] || !ok[c[x[0].second]]) continue;
    s = 0;
    for (auto &i : x) {
      int a = uff.leader(i.first), b = uff.leader(i.second);
      if (r[a] == -1) {
        r[a] = s++;
      }
      if (r[b] == -1) {
        r[b] = s++;
      }
    }
    dsu p(s * 4);
    for (int i = int(0); i < int(s); i++) {
      int a = i, b = i + s * 2;
      p.merge(a, b + s);
      p.merge(b, a + s);
    }
    for (auto &i : x) {
      int a = r[uff.leader(i.first)], b = r[uff.leader(i.second)];
      if (ir[i.first] == 1) a += s * 2;
      if (ir[i.second] == 1) b += s * 2;
      p.merge(a, b + s);
      p.merge(b, a + s);
    }
    bool yes = true;
    for (int i = int(0); i < int(s); i++) {
      int a = i, b = i + s * 2;
      if (p.same(a, a + s)) yes = false;
      if (p.same(b, b + s)) yes = false;
    }
    if (!yes) ans--;
    for (auto &i : x) {
      r[uff.leader(i.first)] = -1;
      r[uff.leader(i.second)] = -1;
    }
  }
  print(ans);
}
