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.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.stream.IntStream;
import java.util.Arrays;
import java.io.IOException;
import java.util.function.IntPredicate;
import java.util.ArrayList;
import java.io.UncheckedIOException;
import java.util.List;
import java.util.stream.Stream;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 29);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            ECaseOfComputerNetwork solver = new ECaseOfComputerNetwork();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class ECaseOfComputerNetwork {
        int[] upAdd;
        int[] botAdd;
        int[] p;
        int[] depth;
        List<UndirectedEdge>[] tree;
        boolean[] visited;
        boolean ok = true;

        void dfs(int root, int p) {
            visited[root] = true;
            depth[root] = p == -1 ? 0 : depth[p] + 1;
            this.p[root] = p;
            for (UndirectedEdge e : tree[root]) {
                if (e.to == p) {
                    continue;
                }
                dfs(e.to, root);
            }
        }

        void trySet(int root, int p) {
            visited[root] = true;
            for (UndirectedEdge e : tree[root]) {
                if (e.to == p) {
                    continue;
                }
                trySet(e.to, root);
                upAdd[root] += upAdd[e.to];
                botAdd[root] += botAdd[e.to];
            }
            assert upAdd[root] >= 0;
            assert botAdd[root] >= 0;
            if (upAdd[root] > 0 && botAdd[root] > 0) {
                ok = false;
            }
        }

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.ri();
            int m = in.ri();
            int q = in.ri();
            p = new int[n];
            Arrays.fill(p, -1);
            depth = new int[n];
            visited = new boolean[n];
            upAdd = new int[n];
            botAdd = new int[n];
            tree = Graph.createGraph(n);
            List<UndirectedEdge>[] g = Graph.createGraph(n);
            DSU dsu = new DSU(n);
            dsu.init();
            for (int i = 0; i < m; i++) {
                int u = in.ri() - 1;
                int v = in.ri() - 1;
                Graph.addUndirectedEdge(g, u, v);
                dsu.merge(u, v);
            }
            UndirectedTarjanSCC scc = new UndirectedTarjanSCC(n);

            scc.init(g);
            for (int i = 0; i < n; i++) {
                for (UndirectedEdge e : g[i]) {
                    if (scc.set[e.to] < scc.set[i]) {
                        Graph.addUndirectedEdge(tree, scc.set[i], scc.set[e.to]);
                    }
                }
            }
            boolean[] isRoot = new boolean[n];
            for (int i = 0; i < n; i++) {
                if (scc.set[i] != i || visited[i]) {
                    continue;
                }
                isRoot[i] = true;
                dfs(i, -1);
            }
            LcaOnTree lca = new LcaOnTree(n);
            lca.init(tree, i -> isRoot[i]);
            for (int i = 0; i < q; i++) {
                int u = scc.set[in.ri() - 1];
                int v = scc.set[in.ri() - 1];
                if (dsu.find(u) != dsu.find(v)) {
                    out.println("No");
                    return;
                }
                int l = lca.lca(u, v);
                //u to v
                upAdd[u]++;
                upAdd[l]--;
                botAdd[v]++;
                botAdd[l]--;
            }

            Arrays.fill(visited, false);
            for (int i = 0; i < n; i++) {
                if (scc.set[i] != i || visited[i]) {
                    continue;
                }
                trySet(i, -1);
            }
            if (ok) {
                out.println("Yes");
            } else {
                out.println("No");
            }
        }

    }

    static class Graph {
        public static UndirectedEdge addUndirectedEdge(List<UndirectedEdge>[] g, int s, int t) {
            UndirectedEdge toT = new UndirectedEdge(t);
            UndirectedEdge toS = new UndirectedEdge(s);
            toT.rev = toS;
            toS.rev = toT;
            g[s].add(toT);
            g[t].add(toS);
            return toT;
        }

        public static List[] createGraph(int n) {
            return IntStream.range(0, n).mapToObj(i -> new ArrayList<>()).toArray(i -> new List[i]);
        }

    }

    static interface IntegerStack {
    }

    static interface IntegerIterator {
        boolean hasNext();

        int next();

    }

    static class LcaOnTree {
        int[] parent;
        int[] preOrder;
        int[] i;
        int[] head;
        int[] a;
        int time;

        void dfs1(List<? extends DirectedEdge>[] tree, int u, int p) {
            parent[u] = p;
            i[u] = preOrder[u] = time++;
            for (DirectedEdge e : tree[u]) {
                int v = e.to;
                if (v == p) continue;
                dfs1(tree, v, u);
                if (Integer.lowestOneBit(i[u]) < Integer.lowestOneBit(i[v])) {
                    i[u] = i[v];
                }
            }
            head[i[u]] = u;
        }

        void dfs2(List<? extends DirectedEdge>[] tree, int u, int p, int up) {
            a[u] = up | Integer.lowestOneBit(i[u]);
            for (DirectedEdge e : tree[u]) {
                int v = e.to;
                if (v == p) continue;
                dfs2(tree, v, u, a[u]);
            }
        }

        public void init(List<? extends DirectedEdge>[] tree, IntPredicate isRoot) {
            time = 0;
            for (int i = 0; i < tree.length; i++) {
                if (isRoot.test(i)) {
                    dfs1(tree, i, -1);
                    dfs2(tree, i, -1, 0);
                }
            }
        }

        public LcaOnTree(int n) {
            preOrder = new int[n];
            i = new int[n];
            head = new int[n];
            a = new int[n];
            parent = new int[n];
        }

        public LcaOnTree(List<? extends DirectedEdge>[] tree, IntPredicate isRoot) {
            this(tree.length);
            init(tree, isRoot);
        }

        private int enterIntoStrip(int x, int hz) {
            if (Integer.lowestOneBit(i[x]) == hz)
                return x;
            int hw = 1 << Log2.floorLog(a[x] & (hz - 1));
            return parent[head[i[x] & -hw | hw]];
        }

        public int lca(int x, int y) {
            int hb = i[x] == i[y] ? Integer.lowestOneBit(i[x]) : (1 << Log2.floorLog(i[x] ^ i[y]));
            int hz = Integer.lowestOneBit(a[x] & a[y] & -hb);
            int ex = enterIntoStrip(x, hz);
            int ey = enterIntoStrip(y, hz);
            return preOrder[ex] < preOrder[ey] ? ex : ey;
        }

    }

    static class IntegerDequeImpl implements IntegerDeque {
        private int[] data;
        private int bpos;
        private int epos;
        private static final int[] EMPTY = new int[0];
        private int n;

        public IntegerDequeImpl(int cap) {
            if (cap == 0) {
                data = EMPTY;
            } else {
                data = new int[cap];
            }
            bpos = 0;
            epos = 0;
            n = cap;
        }

        private void expandSpace(int len) {
            while (n < len) {
                n = Math.max(n + 10, n * 2);
            }
            int[] newData = new int[n];
            if (bpos <= epos) {
                if (bpos < epos) {
                    System.arraycopy(data, bpos, newData, 0, epos - bpos);
                }
            } else {
                System.arraycopy(data, bpos, newData, 0, data.length - bpos);
                System.arraycopy(data, 0, newData, data.length - bpos, epos);
            }
            epos = size();
            bpos = 0;
            data = newData;
        }

        public IntegerIterator iterator() {
            return new IntegerIterator() {
                int index = bpos;


                public boolean hasNext() {
                    return index != epos;
                }


                public int next() {
                    int ans = data[index];
                    index = IntegerDequeImpl.this.next(index);
                    return ans;
                }
            };
        }

        public int removeLast() {
            int ans = data[last(epos)];
            epos = last(epos);
            return ans;
        }

        public void addLast(int x) {
            ensureMore();
            data[epos] = x;
            epos = next(epos);
        }

        private int last(int x) {
            return (x == 0 ? n : x) - 1;
        }

        private int next(int x) {
            return x + 1 >= n ? 0 : x + 1;
        }

        private void ensureMore() {
            if (next(epos) == bpos) {
                expandSpace(n + 1);
            }
        }

        public int size() {
            int ans = epos - bpos;
            if (ans < 0) {
                ans += data.length;
            }
            return ans;
        }

        public boolean isEmpty() {
            return bpos == epos;
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (IntegerIterator iterator = iterator(); iterator.hasNext(); ) {
                builder.append(iterator.next()).append(' ');
            }
            return builder.toString();
        }

    }

    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private static final int THRESHOLD = 1 << 13;
        private final Writer os;
        private StringBuilder cache = new StringBuilder(THRESHOLD * 2);

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

        private void afterWrite() {
            if (cache.length() < THRESHOLD) {
                return;
            }
            flush();
        }

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput append(char c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput append(String c) {
            cache.append(c);
            afterWrite();
            return this;
        }

        public FastOutput println(String c) {
            return append(c).println();
        }

        public FastOutput println() {
            return append(System.lineSeparator());
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class Log2 {
        public static int floorLog(int x) {
            if (x <= 0) {
                throw new IllegalArgumentException();
            }
            return 31 - Integer.numberOfLeadingZeros(x);
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int ri() {
            return readInt();
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static interface IntegerDeque extends IntegerStack {
    }

    static class DirectedEdge {
        public int to;

        public DirectedEdge(int to) {
            this.to = to;
        }

        public String toString() {
            return "->" + to;
        }

    }

    static class UndirectedTarjanSCC {
        private List<? extends UndirectedEdge>[] g;
        public int[] low;
        public int[] dfn;
        public int[] set;
        private IntegerDequeImpl dq;
        private int order;
        private boolean[] instk;

        public UndirectedTarjanSCC(int n) {
            low = new int[n];
            dfn = new int[n];
            set = new int[n];
            instk = new boolean[n];
            dq = new IntegerDequeImpl(n);
        }

        public void init(List<? extends UndirectedEdge>[] g) {
            this.g = g;
            Arrays.fill(dfn, 0, g.length, -1);
            order = 0;
            for (int i = 0; i < g.length; i++) {
                if (dfn[i] != -1) {
                    continue;
                }
                dfs(i, null);
                assert dq.isEmpty();
            }
        }

        private void dfs(int root, UndirectedEdge p) {
            if (dfn[root] != -1) {
                return;
            }
            dfn[root] = low[root] = order++;
            instk[root] = true;
            dq.addLast(root);
            for (UndirectedEdge e : g[root]) {
                if (e.rev == p) {
                    continue;
                }
                dfs(e.to, e);
                if (instk[e.to]) {
                    low[root] = Math.min(low[root], low[e.to]);
                }
            }
            if (dfn[root] == low[root]) {
                while (true) {
                    int tail = dq.removeLast();
                    set[tail] = root;
                    instk[tail] = false;
                    if (tail == root) {
                        break;
                    }
                }
            }
        }

    }

    static class DSU {
        protected int[] p;
        protected int[] rank;
        protected int n;

        public DSU(int n) {
            p = new int[n];
            rank = new int[n];
        }

        public void init() {
            init(p.length);
        }

        public void init(int n) {
            this.n = n;
            for (int i = 0; i < n; i++) {
                p[i] = i;
                rank[i] = 0;
            }
        }

        public final int find(int a) {
            if (p[a] == p[p[a]]) {
                return p[a];
            }
            find(p[a]);
            preAccess(a);
            return p[a] = p[p[a]];
        }

        protected void preAccess(int a) {

        }

        protected void preMerge(int a, int b) {

        }

        public final void merge(int a, int b) {
            a = find(a);
            b = find(b);
            if (a == b) {
                return;
            }
            if (rank[a] == rank[b]) {
                rank[a]++;
            }

            if (rank[a] < rank[b]) {
                int tmp = a;
                a = b;
                b = tmp;
            }

            preMerge(a, b);
            p[b] = a;
        }

        public String toString() {
            return Arrays.toString(Arrays.copyOf(p, n));
        }

    }

    static class UndirectedEdge extends DirectedEdge {
        public UndirectedEdge rev;

        public UndirectedEdge(int to) {
            super(to);
        }

        public String toString() {
            return String.format("%d<->%d", Math.min(rev.to, to), Math.max(rev.to, to));
        }

    }
}

