Andrewid the Android is a galaxy-known detective. Now he is preparing a defense against a possible attack by hackers on a major computer network.

In this network are n vertices, some pairs of vertices are connected by m undirected channels. It is planned to transfer q important messages via this network, the i-th of which must be sent from vertex si to vertex di via one or more channels, perhaps through some intermediate vertices.

To protect against attacks a special algorithm was developed. Unfortunately it can be applied only to the network containing directed channels. Therefore, as new channels can't be created, it was decided for each of the existing undirected channels to enable them to transmit data only in one of the two directions.

Your task is to determine whether it is possible so to choose the direction for each channel so that each of the q messages could be successfully transmitted.

Input

The first line contains three integers n, m and q (1 ≤ n, m, q ≤ 2·105) — the number of nodes, channels and important messages.

Next m lines contain two integers each, vi and ui (1 ≤ vi, ui ≤ n, vi ≠ ui), that means that between nodes vi and ui is a channel. Between a pair of nodes can exist more than one channel.

Next q lines contain two integers si and di (1 ≤ si, di ≤ n, si ≠ di) — the numbers of the nodes of the source and destination of the corresponding message.

It is not guaranteed that in it initially possible to transmit all the messages.

Output

If a solution exists, print on a single line "Yes" (without the quotes). Otherwise, print "No" (without the quotes).

Examples

Input

4 4 2
1 2
1 3
2 3
3 4
1 3
4 2


Output

Yes


Input

3 2 2
1 2
3 2
1 3
2 1


Output

No


Input

3 3 2
1 2
1 2
3 2
1 3
2 1


Output

Yes

Note

In the first sample test you can assign directions, for example, as follows: 1 → 2, 1 → 3, 3 → 2, 4 → 3. Then the path for for the first message will be 1 → 3, and for the second one — 4 → 3 → 2.

In the third sample test you can assign directions, for example, as follows: 1 → 2, 2 → 1, 2 → 3. Then the path for the first message will be 1 → 2 → 3, and for the second one — 2 → 1.
#include <bits/stdc++.h>
using namespace std;
const int INF = 1 << 30;
const long long int MAX = 1e9 + 7;
void array_show(int* array, int array_n, char middle = ' ') {
  for (int i = 0; i < array_n; i++)
    printf("%d%c", array[i], (i != array_n - 1 ? middle : '\n'));
}
void array_show(long long int* array, int array_n, char middle = ' ') {
  for (int i = 0; i < array_n; i++)
    printf("%lld%c", array[i], (i != array_n - 1 ? middle : '\n'));
}
void array_show(vector<int>& vec_s, int vec_n = -1, char middle = ' ') {
  if (vec_n == -1) vec_n = vec_s.size();
  for (int i = 0; i < vec_n; i++)
    printf("%d%c", vec_s[i], (i != vec_n - 1 ? middle : '\n'));
}
void array_show(vector<long long int>& vec_s, int vec_n = -1,
                char middle = ' ') {
  if (vec_n == -1) vec_n = vec_s.size();
  for (int i = 0; i < vec_n; i++)
    printf("%lld%c", vec_s[i], (i != vec_n - 1 ? middle : '\n'));
}
class union_find_tree {
 private:
  static constexpr int N = 100005;
  int n;
  queue<int> q1;
  vector<int> parent;
  vector<int> num;

 public:
  void init(int _n) {
    n = _n;
    parent.assign(n, -1);
    num.assign(n, 1);
  }
  union_find_tree(int n_init) {
    assert(n_init >= 0);
    init(n_init);
  }
  union_find_tree() { init(N); }
  int check_parent(int x) {
    assert(x >= 0 && x < n);
    if (parent[x] != -1) {
      q1.push(x);
      return check_parent(parent[x]);
    }
    int a;
    while (!q1.empty()) {
      a = q1.front(), q1.pop();
      parent[a] = x;
    }
    return x;
  }
  bool connect(int x, int y) {
    assert(x >= 0 && x < n);
    assert(y >= 0 && y < n);
    x = check_parent(x), y = check_parent(y);
    if (x == y) return true;
    if (num[x] > num[y]) swap(x, y);
    parent[x] = y;
    num[y] += num[x];
    return false;
  }
  int size(int pos) {
    pos = check_parent(pos);
    return num[pos];
  }
  bool check(int x, int y) {
    assert(x >= 0 && x < n);
    assert(y >= 0 && y < n);
    return check_parent(x) == check_parent(y);
  }
};
class Lowlink {
 private:
  vector<vector<pair<int, int>>> path;
  vector<vector<int>> tree;
  vector<int> ord, lowlink, trans_pos;
  int n = 0, nest = 0;
  int edge_count = 0;
  bool initialized = false, reloaded = false;
  int dfs(int pos, int bef_id, int& cnt, union_find_tree& ua) {
    if (ord[pos] != -1) return -1;
    lowlink[pos] = ord[pos] = cnt++;
    for (auto node : path[pos]) {
      int to = node.first, id = node.second;
      if (id == bef_id) continue;
      if (dfs(to, id, cnt, ua) == -1) {
        lowlink[pos] = min(lowlink[pos], ord[to]);
      } else {
        lowlink[pos] = min(lowlink[pos], lowlink[to]);
        if (lowlink[to] <= ord[pos]) ua.connect(pos, to);
      }
    }
    return 0;
  }

 public:
  void init(int _n) {
    n = _n;
    path.resize(n);
    ord.assign(n, -1);
    lowlink.assign(n, -1);
    trans_pos.assign(n, -1);
    initialized = true;
  }
  Lowlink() {}
  Lowlink(int _n) { init(_n); }
  Lowlink(int _n, int _nest) {
    init(_n);
    nest = _nest;
  }
  void add_edge(int a, int b) {
    assert(0 <= a && a < n);
    assert(0 <= b && b < n);
    path[a].push_back({b, edge_count});
    path[b].push_back({a, edge_count});
    edge_count++;
  }
  void reload() {
    assert(initialized);
    union_find_tree ua(n);
    int i, j;
    int cnt = 0;
    dfs(nest, -1, cnt, ua);
    cnt = 0;
    for (i = 0; i < n; i++) {
      j = ua.check_parent(i);
      if (trans_pos[j] == -1) trans_pos[j] = cnt++;
      if (i != j) trans_pos[i] = trans_pos[j];
    }
    unordered_set<long long int> exist_edge;
    tree.resize(cnt);
    for (i = 0; i < n; i++) {
      int pos = trans_pos[i];
      for (auto node : path[i]) {
        int to = trans_pos[node.first];
        if (pos == to) continue;
        if (exist_edge.find((long long int)pos * n + to) != exist_edge.end())
          continue;
        exist_edge.insert((long long int)pos * n + to);
        tree[pos].push_back(to);
      }
    }
    reloaded = true;
  }
  vector<vector<int>>& get_tree() {
    assert(reloaded);
    return tree;
  }
  vector<int>& get_trans_pos() {
    assert(reloaded);
    return trans_pos;
  }
  int get_trans_pos(int pos) const {
    assert(reloaded);
    assert(0 <= pos && pos < n);
    return trans_pos[pos];
  }
};
class Lca {
 private:
  const int M = 20;
  int nest = 0;
  vector<vector<int>> path;
  vector<vector<int>> par;
  vector<int> depth;
  void init(int n) {
    path.assign(n, vector<int>());
    par.assign(n, vector<int>(M, -1));
    depth.assign(n, -1);
  }
  void create_depth(int pos, int bef, int d) {
    if (depth.at(pos) != -1) return;
    depth.at(pos) = d;
    int p = bef;
    for (int i = 0; i < M; i++) {
      if (p == -1) break;
      par.at(pos).at(i) = p;
      p = par.at(p).at(i);
    }
    for (auto to : path.at(pos)) {
      create_depth(to, pos, d + 1);
    }
  }

 public:
  Lca(int n) { init(n); }
  Lca(int n, int nes) {
    nest = nes;
    init(n);
  }
  int get_depth(int pos) { return depth.at(pos); }
  void connect(int a, int b) {
    path.at(a).push_back(b);
    path.at(b).push_back(a);
  }
  void reload() {
    int n = path.size();
    par.assign(n, vector<int>(M, -1));
    depth.assign(n, -1);
    create_depth(nest, -1, 0);
  }
  int check_parent(int pos, int dis) {
    assert(0 <= dis && dis <= depth[pos]);
    if (dis == 0) return pos;
    for (int i = M - 1; i >= 0; i--) {
      if (dis < (1 << i)) continue;
      dis -= 1 << i;
      pos = par.at(pos).at(i);
    }
    return pos;
  }
  int lca(int a, int b) {
    if (depth.at(a) < depth.at(b)) swap(a, b);
    a = check_parent(a, depth.at(a) - depth.at(b));
    if (a == b) return a;
    for (int i = M - 1; i >= 0; i--) {
      if (par.at(a).at(i) != par.at(b).at(i)) {
        a = par.at(a).at(i);
        b = par.at(b).at(i);
      }
    }
    return par.at(a).at(0);
  }
  int distance(int a, int b) {
    return depth.at(a) + depth.at(b) - 2 * depth.at(lca(a, b));
  }
};
namespace sol {
int t[222222][3];
bool dfs(int pos, int bef, vector<vector<int>>& tree) {
  for (auto to : tree[pos]) {
    if (to == bef) continue;
    if (!dfs(to, pos, tree)) return false;
    for (int i = 0; i < 3; i++) {
      t[pos][i] += t[to][i];
    }
  }
  if (t[pos][0] > t[pos][2] && t[pos][1] > t[pos][2]) return false;
  return true;
}
void solve() {
  int n, m, q;
  int i;
  int a, b, c;
  cin >> n >> m >> q;
  Lowlink loli(n + 1);
  union_find_tree ua(n);
  for (i = 0; i < m; i++) {
    cin >> a >> b;
    a--, b--;
    loli.add_edge(a + 1, b + 1);
    ua.connect(a, b);
  }
  for (i = 0; i < n; i++) {
    if (ua.check_parent(i) == i) loli.add_edge(i + 1, 0);
  }
  loli.reload();
  vector<vector<int>> tree = loli.get_tree();
  n = tree.size();
  Lca lca(n);
  for (i = 0; i < n; i++) {
    for (auto to : tree[i]) {
      if (i < to) lca.connect(i, to);
    }
  }
  lca.reload();
  for (i = 0; i < q; i++) {
    cin >> a >> b;
    a = loli.get_trans_pos(a), b = loli.get_trans_pos(b);
    t[a][0]++, t[b][1]++;
    c = lca.lca(a, b);
    if (c == 0) {
      cout << "No" << endl;
      return;
    }
    t[c][2]++;
  }
  if (dfs(0, -1, tree))
    cout << "Yes" << endl;
  else
    cout << "No" << endl;
}
}  // namespace sol
int main() { sol::solve(); }
