#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstring>
#include <functional>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <istream>
#include <map>
#include <math.h>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace asl
{
typedef long long i64;
#include <stdint.h>
template <typename T>
using vec = std::vector<T>;
class DisjointSet
{
bool with_path_compression;
public:
std::vector<int> ds;
DisjointSet(int n, bool with_path_compression = true) : with_path_compression(with_path_compression)
{
ds = std::vector<int>(n, -1);
}
int root(int a)
{
if (ds[a] < 0)
return a;
else
{
if (with_path_compression)
return ds[a] = root(ds[a]);
else
return root(ds[a]);
}
}
bool join(int u, int v)
{
u = root(u), v = root(v);
if (u == v)
{
on_equal(u);
return false;
}
if (ds[u] < ds[v])
std::swap(u, v);
on_join(u, v);
ds[v] += ds[u];
ds[u] = v;
return true;
}
virtual void on_join(int u, int v)
{
}
virtual void on_equal(int u)
{
}
};
} // namespace asl
namespace asl
{
template <typename T>
std::vector<std::vector<T>> board(int n, int m, T def)
{
return std::vector<std::vector<T>>(n, std::vector<T>(m, def));
}
template <typename T>
std::vector<std::vector<T>> board(int n = 0, int m = 0)
{
return std::vector<std::vector<T>>(n, std::vector<T>(m));
}
} // namespace asl
#include <utility>
#include <tuple>
#include <random>
#define endl '\n'
using namespace std;
using namespace asl;
vec<int> base3(int num)
{
vec<int> res;
for (int i = 0; i < 3; ++i)
{
res.push_back(num % 3);
num /= 3;
}
return res;
}
bool valid(vec<int> &row)
{
int p = 0;
for (int i = 0; i < 3; ++i)
{
if (row[i] > p)
return false;
if (row[i] == p)
++p;
}
return true;
}
bool test(int mask, int bit)
{
return mask >> bit & 1;
}
vec<int> canonic(vec<int> order)
{
map<int, int> m;
int p = 0;
for (int i = 0; i < 3; ++i)
{
if (!m.count(order[i]))
m[order[i]] = p++;
order[i] = m[order[i]];
}
return order;
}
struct state
{
vec<int> order;
int mask;
bool is_end()
{
int t = 0;
for (int x = 0; x < 3; ++x)
if (test(mask, x))
{
++t;
for (int y = 0; y < x; ++y)
if (order[x] != order[y] && test(mask, y))
return false;
}
return t > 0;
}
bool operator==(const state &s) const
{
return order == s.order && mask == s.mask;
}
} S[100];
int TOTAL;
bool END[100];
bool VALID[100][1 << 5][1 << 3];
int GO[100][1 << 5][1 << 3];
void calc(int state_id, int wall, int person)
{
state s = S[state_id];
DisjointSet ds(7);
for (int x = 0; x < 3; ++x)
for (int y = 0; y < 3; ++y)
if (s.order[x] == s.order[y])
ds.join(x, y);
for (int i = 0; i < 3; ++i)
if (wall >> i & 1)
ds.join(i, i + 3);
if (wall >> 3 & 1)
ds.join(3, 4);
if (wall >> 4 & 1)
ds.join(4, 5);
auto tmp = ds;
for (int i = 0; i < 3; ++i)
tmp.join(i + 3, 6);
int r = tmp.root(6);
for (int i = 0; i < 3; ++i)
if ((s.mask >> i & 1) && tmp.root(i) != r)
{
VALID[state_id][wall][person] = false;
return;
}
vec<bool> per(6);
for (int i = 0; i < 3; ++i)
{
if (s.mask >> i & 1)
per[ds.root(i)] = true;
if (person >> i & 1)
per[ds.root(i + 3)] = true;
}
int new_mask = 0;
vec<int> tmp_ord(3);
for (int i = 0; i < 3; ++i)
{
tmp_ord[i] = ds.root(i + 3);
if (per[ds.root(i + 3)])
new_mask |= 1 << i;
}
state ns = {canonic(tmp_ord), new_mask};
int id = -1;
for (int i = 0; i < TOTAL; ++i)
if (ns == S[i])
{
id = i;
break;
}
assert(id >= 0);
VALID[state_id][wall][person] = true;
GO[state_id][wall][person] = id;
}
void pre()
{
TOTAL = 0;
for (int i = 0; i < 27; ++i)
{
auto row = base3(i);
if (!valid(row))
continue;
for (int mask = 0; mask < 8; ++mask)
{
bool good = true;
for (int x = 0; x < 3 && good; ++x)
for (int y = 0; y < x && good; ++y)
if (row[x] == row[y])
good &= test(mask, x) == test(mask, y);
if (!good)
continue;
S[TOTAL] = {row, mask};
END[TOTAL] = S[TOTAL].is_end();
TOTAL++;
}
}
int good = 0;
int bad = 0;
for (int s = 0; s < TOTAL; ++s)
for (int wall = 0; wall < (1 << 5); ++wall)
for (int person = 0; person < (1 << 3); ++person)
{
calc(s, wall, person);
if (VALID[s][wall][person])
good++;
else
bad++;
}
}
void solve()
{
pre();
int n, m;
cin >> n >> m;
auto a = board<i64>(3, n, 1e18);
auto b = board<i64>(2, n);
for (int i = 0; i < 3; ++i)
for (int j = 1; j < n; ++j)
cin >> a[i][j];
for (int i = 0; i < 2; ++i)
for (int j = 0; j < n; ++j)
cin >> b[i][j];
vec<int> people(n);
int last = -1;
for (int i = 0; i < m; ++i)
{
int x, y;
cin >> x >> y;
--x;
--y;
people[y] |= 1 << x;
last = max(last, y);
}
auto cost = [&](int p, int wall) {
i64 r = 0;
for (int i = 0; i < 3; ++i)
if (wall >> i & 1)
r += a[i][p];
if (wall >> 3 & 1)
r += b[0][p];
if (wall >> 4 & 1)
r += b[1][p];
return r;
};
const i64 inf = 1e18;
vec<i64> dp(TOTAL, inf);
vec<i64> memo(1 << 5);
dp[0] = 0;
i64 res = inf;
for (int i = 0; i < n; ++i)
{
vec<i64> ndp(TOTAL, inf);
int p = people[i];
for (int wall = 0; wall < (1 << 5); ++wall)
memo[wall] = cost(i, wall);
for (int s = 0; s < TOTAL; ++s)
for (int wall = 0; wall < (1 << 5); ++wall)
{
if (VALID[s][wall][p])
{
int ns = GO[s][wall][p];
ndp[ns] = min(ndp[ns], dp[s] + memo[wall]);
}
}
dp.swap(ndp);
if (i >= last)
for (int s = 0; s < TOTAL; ++s)
if (END[s])
res = min(res, dp[s]);
}
cout << res << endl;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
int t = 1;
for (int i = 1; i <= t; ++i)
{
solve();
}
return 0;
}