#include <bits/stdc++.h>
#pragma GCC optimize(3)
using std::cerr;
using std::cout;
using std::endl;
using std::fill;
using std::min;
using std::unordered_map;
using std::unordered_set;
using std::vector;
const long long mod = 1e+9 + 7;
const int maxn = 5e+5 + 5;
struct edge {
  long long frm, to;
  edge(long long f_ = 0, long long t_ = 0) : frm(f_), to(t_) {}
};
long long n, m, k;
long long ans, c[maxn];
unordered_map<long long, vector<edge> > e_mp;
unordered_map<long long, long long> f;
long long find(long long x) {
  return (!f.count(x) || f[x] == x) ? x : f[x] = find(f[x]);
}
inline long long quick_power(long long base, long long index) {
  long long ret = 1;
  while (index) {
    if (index & 1) ret = (ret * base) % mod;
    index >>= 1;
    base = base * base % mod;
  }
  return ret % mod;
}
int main() {
  scanf("%I64d%I64d%I64d", &n, &m, &k);
  for (long long i = 1; i <= n; ++i) scanf("%I64d", &c[i]);
  for (long long i = 1; i <= m; ++i) {
    long long u, v;
    scanf("%I64d%I64d", &u, &v);
    long long x = (c[u] ^ c[v]);
    e_mp[x].push_back(edge(u, v));
  }
  for (auto vec : e_mp) {
    f.clear();
    unordered_set<long long> dsu;
    for (auto pr : vec.second) {
      long long fx = find(pr.frm), fy = find(pr.to);
      if (fx < fy)
        f[fy] = fx;
      else
        f[fx] = fy;
      dsu.insert(pr.frm);
      dsu.insert(pr.to);
    }
    long long single_p = dsu.size();
    dsu.clear();
    for (auto pr : vec.second) dsu.insert(find(min(pr.frm, pr.to)));
    ans = (ans + quick_power(2ll, dsu.size() + n - single_p)) % mod;
  }
  ans = ans + quick_power(2ll, n) * (quick_power(2ll, k) - e_mp.size());
  ans = (ans % mod + mod) % mod;
  cout << ans << endl;
  return 0;
}
