#include <bits/stdc++.h>
using namespace std;
bool debug;
struct FlowEdge {
  int from, to;
  long long flow = 0, capacity;
  FlowEdge(int from, int to, long long capacity)
      : from(from), to(to), capacity(capacity) {}
};
struct Dinic {
 public:
  int n, m = 0, start, target;
  vector<FlowEdge> edges;
  vector<vector<long long> > adj;
  Dinic(int n, int start, int target) : n(n), start(start), target(target) {
    level.resize(n);
    ptr.resize(n);
    adj.resize(n);
  }
  void addEdge(int from, int to, long long capacity) {
    edges.emplace_back(from, to, capacity);
    edges.emplace_back(to, from, 0);
    adj[from].push_back(m);
    adj[to].push_back(m + 1);
    m += 2;
  }
  long long maxFlow() {
    long long flow = 0;
    while (true) {
      if (!bfs()) break;
      ptr.assign(n, 0);
      while (long long pushed = augment(start, FLOW_INF)) {
        if (debug) {
          cout << "pushed"
               << ": " << pushed << endl;
        }
        flow += pushed;
      }
    }
    if (debug) {
      cout << "flow"
           << ": " << flow << endl;
    }
    return flow;
  }
  vector<FlowEdge> getUsedEdges() {
    vector<FlowEdge> res;
    for (int i = 0; i < m; i += 2) {
      if (edges[i].flow > 0) {
        res.push_back(edges[i]);
      }
    }
    return res;
  }

 private:
  vector<long long> level, ptr;
  const long long FLOW_INF = 1e18;
  bool bfs() {
    level.assign(n, -1);
    level[start] = 0;
    queue<int> mq;
    mq.push(start);
    while (!mq.empty()) {
      int curr = mq.front();
      mq.pop();
      for (int id : adj[curr]) {
        if (level[edges[id].to] != -1) continue;
        if (edges[id].capacity - edges[id].flow < 1) continue;
        level[edges[id].to] = level[curr] + 1;
        mq.push(edges[id].to);
      }
    }
    return level[target] != -1;
  }
  long long augment(int u, long long currFlow) {
    if (currFlow == 0) return 0;
    if (u == target) return currFlow;
    for (int i = ptr[u]; i < adj[u].size(); i++, ptr[u]++) {
      int id = adj[u][i];
      int v = edges[id].to;
      if (level[u] + 1 != level[v] || edges[id].capacity - edges[id].flow < 1)
        continue;
      long long nextFlow =
          augment(v, min(edges[id].capacity - edges[id].flow, currFlow));
      if (nextFlow == 0) continue;
      edges[id].flow += nextFlow;
      edges[id ^ 1].flow -= nextFlow;
      return nextFlow;
    }
    return 0;
  }
};
int main(int argc, char *argv[]) {
  debug = argc > 1;
  int n, m;
  cin >> n >> m;
  int source = 0, sink = 2 * n + 1;
  Dinic dinic(2 * n + 2, source, sink);
  vector<long long> a(n + 1), b(n + 1);
  long long totalA = 0;
  long long total = 0;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
    totalA += a[i];
    dinic.addEdge(source, i, a[i]);
    dinic.addEdge(i, i + n, a[i]);
  }
  for (int i = 1; i <= n; i++) {
    cin >> b[i];
    dinic.addEdge(i, sink, b[i]);
    total += b[i];
  }
  int u, v;
  for (int i = 0; i < m; i++) {
    cin >> u >> v;
    dinic.addEdge(u + n, v, a[u]);
    dinic.addEdge(v + n, u, a[v]);
  }
  if (debug) {
    cout << "\"done\""
         << ": "
         << "done" << endl;
  }
  long long mf = dinic.maxFlow();
  if (totalA == total && total == mf) {
    cout << "YES" << endl;
    vector<vector<long long> > ans(n, vector<long long>(n, 0));
    for (int i = 0; i < n; i++) {
      ans[i][i] = a[i + 1];
    }
    vector<FlowEdge> edges = dinic.getUsedEdges();
    for (FlowEdge e : edges) {
      if (e.from > n && e.from < sink && e.to > 0 && e.to <= n) {
        ans[e.from - 1 - n][e.to - 1] += e.flow;
        ans[e.from - 1 - n][e.from - 1 - n] -= e.flow;
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        cout << ans[i][j] << ' ';
      }
      cout << endl;
    }
  } else {
    cout << "NO\n" << endl;
  }
  return 0;
}
