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.
import java.io.*;
import java.util.*;

public class P555E implements Runnable {
    static class InputReader {
        final BufferedReader rd;
        StringTokenizer tok = null;
        InputReader(String fileName) throws IOException { rd = new BufferedReader(new FileReader(fileName)); }
        InputReader(InputStream inputStream) throws IOException { rd = new BufferedReader(new InputStreamReader(inputStream)); }
        String nextToken() throws IOException {
            while (tok == null || !tok.hasMoreTokens()) {
                tok = new StringTokenizer(rd.readLine());
            }
            return tok.nextToken();
        }
        int nextInt() throws IOException { return Integer.parseInt(nextToken()); }
        void close() { try { rd.close(); } catch (Exception e) {} }
    }

    public static void main(String[] args) { new Thread(new P555E()).start(); }
    @Override public void run() { try { solve(); } catch (Exception e) { throw new RuntimeException(e); } }

    static class Edge {
        final int to;
        Edge pair = null;
        Edge(int to) { this.to = to; }
    }

    static class DSS {
        int[] par;
        final Random r = new Random();
        DSS(int n) {
            r.setSeed(239);
            par = new int[n];
            for (int i = 0; i < n; ++i) {
                par[i] = i;
            }
        }
        int find(int x) {
            if (par[x] != x) {
                par[x] = find(par[x]);
            }
            return par[x];
        }
        void unite(int x, int y) {
            x = find(x);
            y = find(y);
            if (r.nextBoolean()) {
                par[x] = y;
            } else {
                par[y] = x;
            }
        }
    }

    int n;
    ArrayList<Edge>[] edges;
    DSS dss;

    ArrayList<Edge>[] cedges;
    boolean[] cv;
    int[] cl;
    int[] cp;
    int[][] cpl;
    int[] froms;
    int[] tos;

    class Condenser {
        final int[] tenter;
        final int[] tmin;
        int time;
        final DSS dss;
        Condenser() {
            dss = new DSS(n);
            tenter = new int[n];
            tmin = new int[n];
            Arrays.fill(tenter, -1);
            time = 0;
        }
        DSS condense() {
            for (int i = 0; i < n; ++i) {
                if (tenter[i] == -1) {
                    dfs(i, null);
                }
            }
            return dss;
        }
        void dfs(int x, Edge pe) {
            tenter[x] = time;
            tmin[x] = time;
            ++time;

            for (Edge e : edges[x]) {
                if (e.pair == pe) {
                    continue;
                }
                if (tenter[e.to] == -1) {
                    dfs(e.to, e);
                }
                if (tmin[e.to] < tmin[x]) {
                    tmin[x] = tmin[e.to];
                    dss.unite(x, e.to);
                }
            }
        }
    }

    void condense() {
        dss = new Condenser().condense();
        cedges = new ArrayList[n];
        cv = new boolean[n];
        Arrays.fill(cv, false);
        for (int i = 0; i < n; ++i) {
            cedges[i] = new ArrayList<Edge>();
        }
        for (int i = 0; i < n; ++i) {
            int x = dss.find(i);
            cv[x] = true;
            for (Edge e : edges[i]) {
                int y = dss.find(e.to);
                Edge xy = new Edge(y);
                if (x != y) {
                    cedges[x].add(xy);
                    cv[y] = true;
                }
            }
        }
    }

    static final String NO = "No";
    static final String YES = "Yes";
    static final int LOGN = 18;

    void solve() throws IOException {
        InputReader rd = new InputReader(System.in);
        PrintWriter wr = new PrintWriter(System.out);

//        System.err.println("read");

        n = rd.nextInt();

        edges = new ArrayList[n];
        for (int i = 0; i < n; ++i) {
            edges[i] = new ArrayList<Edge>();
        }

        int m = rd.nextInt();
        int q = rd.nextInt();
        for (int i = 0; i < m; ++i) {
            int u = rd.nextInt() - 1;
            int v = rd.nextInt() - 1;
            Edge uv = new Edge(v);
            Edge vu = new Edge(u);
            uv.pair = vu;
            vu.pair = uv;
            edges[u].add(uv);
            edges[v].add(vu);
        }

//        System.err.println("condense");
        condense();
//        System.err.println("root");
        root();
//        System.err.println("preprocessLCA");
        preprocessLCA();

//        System.err.println("finish");
        froms = new int[n];
        tos = new int[n];
        for (int i = 0; i < n; ++i) {
            froms[i] = 0;
            tos[i] = 0;
        }

        for (int i = 0; i < q; ++i) {
            int s = rd.nextInt() - 1;
            int d = rd.nextInt() - 1;
            s = dss.find(s);
            d = dss.find(d);
            if (s != d) {
                ++froms[s];
                ++tos[d];
                int t = lca(s, d);
                if (t == -1) {
                    wr.println(NO);
                    rd.close();
                    wr.close();
                    return;
                }
                --froms[t];
                --tos[t];
            }
        }

        if (traverse()) {
            wr.println(YES);
        } else {
            wr.println(NO);
        }

        rd.close();
        wr.close();
    }

    void root() {
        cp = new int[n];
        cl = new int[n];
        Arrays.fill(cp, -1);
        Arrays.fill(cl, 0);
        for (int i = 0; i < n; ++i) {
            if (cv[i] && cp[i] == -1) {
                rootDFS(i);
            }
        }
    }

    void rootDFS(int x) {
        for (Edge e : cedges[x]) {
            if (e.to == cp[x]) {
                continue;
            }
            cp[e.to] = x;
            cl[e.to] = cl[x] + 1;
            rootDFS(e.to);
        }
    }

    void preprocessLCA() {
        cpl = new int[n][LOGN + 1];
        for (int i = 0; i < n; ++i) {
            if (!cv[i]) {
                continue;
            }
            for (int j = 0; j <= LOGN; ++j) {
                cpl[i][j] = -1;
            }
        }
        for (int i = 0; i < n; ++i) {
            if (!cv[i]) {
                continue;
            }
            cpl[i][0] = cp[i];
        }
        for (int j = 1; j <= LOGN; ++j) {
            for (int i = 0; i < n; ++i) {
                if (!cv[i]) {
                    continue;
                }
                if (cpl[i][j - 1] != -1) {
                    cpl[i][j] = cpl[cpl[i][j - 1]][j - 1];
                }
            }
        }
    }

    int lca(int x, int y) {
        if (!cv[x] || !cv[y]) {
            return -1;
        }
        if (cl[x] > cl[y]) {
            int t = x;
            x = y;
            y = t;
        }
        int diff = cl[y] - cl[x];
        for (int i = LOGN; i >= 0; --i) {
            int step = 1 << i;
            if (diff >= step) {
                y = cpl[y][i];
                if (y == -1) {
                    throw new AssertionError();
                }
                diff -= step;
            }
        }
        if (x == y) {
            return x;
        }
        for (int i = LOGN; i >= 0; --i) {
            if (cl[x] != cl[y]) {
                throw new AssertionError();
            }
            if (cpl[x][i] != -1 && cpl[y][i] != -1 && cpl[x][i] != cpl[y][i]) {
                x = cpl[x][i];
                y = cpl[y][i];
            }
        }
        x = cp[x];
        y = cp[y];
        if (x != y) {
            return -1;
        }
        return x;
    }

    boolean traverse() {
        for (int i = 0; i < n; ++i) {
            if (cv[i] && cp[i] == -1) {
                if (!traverseDFS(i)) {
                    return false;
                }
            }
        }
        return true;
    }

    boolean traverseDFS(int x) {
        for (Edge e : cedges[x]) {
            int nx = e.to;
            if (nx == cp[x]) {
                continue;
            }
            if (!traverseDFS(nx)) {
                return false;
            }
            froms[x] += froms[nx];
            tos[x] += tos[nx];
        }
        if (froms[x] != 0 && tos[x] != 0) {
            return false;
        }
        return true;
    }
}
