#pragma GCC optimize("O3")
#pragma GCC target("avx")
#include <cstdio>
#include <functional>
#include <queue>
#include <tuple>
using namespace std;

int main() {
    int R, C;
    scanf("%d%d", &R, &C);
    int A[250000], B[250000];
    int dist[500000], seen[500000] = {0}, cost, pt, to_hide = R * C;
    priority_queue<pair<int, int>, vector<pair<int, int>>,greater<pair<int, int>>>queue;
    for(int i = 0; i < R * C; ++i)
        if(i % C != C - 1) scanf("%d", &A[i]);
    for(int i = 0; i < (R - 1) * C; ++i) scanf("%d", &B[i]);
    for(int i = 1; i < to_hide + to_hide; ++i) dist[i] = 10000000;
    queue.emplace(pair<int, int>(0, 0));
    while(!queue.empty()) {
        tie(cost, pt) = queue.top();
      	if(pt == to_hide - 1)break;
        queue.pop();
        seen[pt] = true;
        if(pt < to_hide) {
            if(!seen[pt + 1] && pt % C != C - 1) {
                if(cost + A[pt] < dist[pt + 1]) {
                    dist[pt + 1] = cost + A[pt];
                    queue.emplace(pair<int, int>(dist[pt + 1], pt + 1));
                }
            }
            if(!seen[pt - 1] && pt % C != 0) {
                if(cost + A[pt - 1] < dist[pt - 1]) {
                    dist[pt - 1] = cost + A[pt - 1];
                    queue.emplace(pair<int, int>(dist[pt - 1], pt - 1));
                }
            }
            if(!seen[pt + C] && pt < to_hide - C) {
                if(cost + B[pt] < dist[pt + C]) {
                    dist[pt + C] = cost + B[pt];
                    queue.emplace(pair<int, int>(dist[pt + C], pt + C));
                }
            }
            if(!seen[pt + to_hide] && cost + 1 < dist[pt + to_hide]) {
                dist[pt + to_hide] = cost + 1;
                queue.emplace(pair<int, int>(dist[pt + to_hide], pt + to_hide));
            }
        } else {
            if(to_hide < pt - C && !seen[pt - C] && cost + 1 < dist[pt - C]) {
                dist[pt - C] = cost + 1;
                queue.emplace(pair<int, int>(cost + 1, pt - C));
            }
            if(!seen[pt - to_hide] && cost < dist[pt - to_hide]) {
                dist[pt - to_hide] = cost;
                queue.emplace(pair<int, int>(cost, pt - to_hide));
            }
        }
    }
    printf("%d\n", dist[to_hide - 1]);
}
// #include "pch.h"
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <climits>
#include <string>
#include <cmath>
#include <bitset>
#include <complex>
#include <functional>
#include <ctime>
#include <cassert>
#include <fstream>
#include <stack>
#include <random>

typedef long long ll;
typedef std::pair<int, int> Pii;
typedef std::pair<long long, long long> Pll;
typedef std::pair<double, double> Pdd;

#define rip(i, n, ss) for (int i = (ss);i < (int)( n ); i++)
#define all(a) a.begin(), a.end()
#define MM << " " <<

template<typename T>
using MaxHeap = std::priority_queue<T>;
template<typename T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template<typename T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template<typename T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

# ifndef ONLINE_JUDGE
template<typename T>
void vdeb(std::vector<T> &bb) {
    for (int i = 0;i < bb.size();i++) {
        if (i == bb.size() - 1) std::cout << bb[i];
        else std::cout << bb[i] << ' ';
    }
    std::cout << '\n';
}
template<typename T>
void vdeb(std::vector<std::vector<T>> &bb) {
    for (int i = 0;i < bb.size();i++) {
        std::cout << i << ' ';
        vdeb(bb[i]);
    }
    std::cout << '\n';
}
# endif

class UnionFind {
    int _n;
    int _size;
    std::vector<int> par_size;

    public:
    UnionFind() :_n(0), _size(0){}
    UnionFind(int n) : _n(n), _size(0), par_size(n, -1) {}

    int unite(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        a = root(a), b = root(b);
        if(a == b) return a;
        _size--;
        if(-par_size[a] < -par_size[b]) {
            par_size[b] += par_size[a];
            return par_size[a] = b;
        }
        else {
            par_size[a] += par_size[b];
            return par_size[b] = a;
        }
    }

    int root(int a) {
        assert(0 <= a && a < _n);
        if(par_size[a] < 0) return a;
        return par_size[a] = root(par_size[a]); 
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return root(a) == root(b);
    }

    int size(int a) {
        assert(0 <= a && a< _n);
        return -par_size[root(a)];
    }

    int size() {return _size;}

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = root(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                        [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }
};

using namespace std;

int main() {
    int n, m; cin >> n >> m;
    vector<ll> a(n);
    rip(i,n,0) cin >> a[i];
    vector<ll> b(n);
    UnionFind  uf(n);
    rip(i,n,0) cin >> b[i];
    rip(i,m,0) {
        int x, y; cin >> x >> y;
        --x;--y;
        uf.unite(x, y);
        uf.unite(y, x);
    }
    auto da = uf.groups();
    rip(i, da.size(), 0) {
        ll aa = 0, bb = 0;
        rip(j,da[i].size(), 0) {
            aa += a[da[i][j]];
            bb += b[da[i][j]];
        }
        if(aa != bb) {
            cout << "No" << endl;
            return  0;
        }
    }
    cout << "Yes" << endl;
}