#include <bits/stdc++.h>
template <class C, class E>
inline bool contains(const C &container, const E &element) {
  return container.find(element) != container.end();
}
template <class T>
inline void checkmin(T &a, T b) {
  if (b < a) a = b;
}
template <class T>
inline void checkmax(T &a, T b) {
  if (b > a) a = b;
}
using namespace std;
long long mod(long long a, long long b) {
  assert(b != 0);
  long long r = a % b;
  return r >= 0 ? r : r + std::abs(b);
}
template <class T>
inline T euclide(T a, T b, T &x, T &y) {
  if (a < 0) {
    T d = euclide(-a, b, x, y);
    x = -x;
    return d;
  }
  if (b < 0) {
    T d = euclide(a, -b, x, y);
    y = -y;
    return d;
  }
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  } else {
    T d = euclide(b, a % b, x, y);
    T t = x;
    x = y;
    y = t - (a / b) * y;
    return d;
  }
}
template <class T>
inline T InvModP(T a, T p) {
  T aInv, dummy, gcdRes;
  gcdRes = euclide(a, p, aInv, dummy);
  assert(gcdRes == 1);
  if (aInv < 0) aInv += p;
  return aInv;
}
struct MI {
  MI() : _val(0) {}
  MI(long long val) : _val(mod(val, 1000000007LL)) {}
  MI operator*(MI other) { return MI(_val * other._val); }
  MI operator*=(MI other) { return *this = *this * other; }
  MI operator+(MI other) { return MI(_val + other._val); }
  MI operator+=(MI other) { return *this = *this + other; }
  MI operator-(MI other) { return MI(_val + (1000000007LL - other._val)); }
  MI operator-=(MI other) { return *this = *this - other; }
  MI operator/(MI other) {
    return *this * InvModP<long long>(other._val, 1000000007LL);
  }
  MI operator/=(MI other) { return *this = *this / other; }
  long long Val() { return _val; }

 private:
  long long _val;
};
int n, m, k;
vector<long long> servers;
vector<pair<int, int>> edges;
MI Pow(MI p, long long e) {
  if (e == 0) return 1;
  if (e % 2 == 0) {
    MI t = Pow(p, e / 2);
    return t * t;
  } else
    return Pow(p, e - 1) * p;
}
vector<bool> visited;
vector<vector<int>> edgesDFS;
int DFS(int index) {
  if (visited[index]) return 0;
  visited[index] = true;
  int res = 1;
  for (int br : edgesDFS[index]) res += DFS(br);
  return res;
}
MI CountUnsafe(const list<int> &edgesIndexes) {
  int current = 0;
  map<int, int> mapping;
  for (int eindex : edgesIndexes) {
    pair<int, int> &edge = edges[eindex];
    if (!contains(mapping, edge.first)) {
      mapping[edge.first] = current;
      ++current;
    }
    if (!contains(mapping, edge.second)) {
      mapping[edge.second] = current;
      ++current;
    }
  }
  int included = mapping.size();
  edgesDFS.clear();
  edgesDFS = vector<vector<int>>(included);
  visited = vector<bool>(included, false);
  for (int eindex : edgesIndexes) {
    pair<int, int> &edge = edges[eindex];
    int a = mapping[edge.first];
    int b = mapping[edge.second];
    edgesDFS[a].push_back(b);
    edgesDFS[b].push_back(a);
  }
  vector<int> componentSizes;
  for (int i = (0), _b = ((included)-1); i <= _b; i++) {
    int cs = DFS(i);
    if (cs != 0) componentSizes.push_back(cs);
  }
  long long notIncluded = n - included;
  MI res = Pow(2, n) - Pow(2, notIncluded + componentSizes.size());
  return res;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  cout << std::setprecision(15);
  cout << std::fixed;
  cin >> n >> m >> k;
  edges.resize(m);
  servers.resize(n);
  for (int i = (0), _b = ((n)-1); i <= _b; i++) cin >> servers[i];
  map<long long, list<int>> medges;
  for (int i = (0), _b = ((m)-1); i <= _b; i++) {
    cin >> edges[i].first >> edges[i].second;
    --edges[i].first;
    --edges[i].second;
    long long dif = servers[edges[i].first] ^ servers[edges[i].second];
    medges[dif].push_back(i);
  }
  MI total = Pow(2, k + n);
  for (auto &me : medges) {
    total -= CountUnsafe(me.second);
  }
  cout << total.Val();
  return 0;
}
