← Home
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

const INF = 1e9

type Edge struct {
	to, cap, flow, rev int
}

var graph [][]Edge
var level []int
var ptr []int
var scanner *bufio.Scanner

func nextInt() int {
	scanner.Scan()
	res, _ := strconv.Atoi(scanner.Text())
	return res
}

func addEdge(from, to, cap int) {
	graph[from] = append(graph[from], Edge{to, cap, 0, len(graph[to])})
	graph[to] = append(graph[to], Edge{from, 0, 0, len(graph[from]) - 1})
}

func bfs(s, t int) bool {
	for i := range level {
		level[i] = -1
	}
	level[s] = 0
	queue := []int{s}
	for len(queue) > 0 {
		v := queue[0]
		queue = queue[1:]
		for _, edge := range graph[v] {
			if edge.cap-edge.flow > 0 && level[edge.to] == -1 {
				level[edge.to] = level[v] + 1
				queue = append(queue, edge.to)
			}
		}
	}
	return level[t] != -1
}

func dfs(v, t, pushed int) int {
	if pushed == 0 {
		return 0
	}
	if v == t {
		return pushed
	}
	for i := ptr[v]; i < len(graph[v]); i++ {
		ptr[v] = i
		edge := graph[v][i]
		tr := edge.to
		if level[v]+1 != level[tr] || edge.cap-edge.flow == 0 {
			continue
		}
		push := pushed
		if edge.cap-edge.flow < push {
			push = edge.cap - edge.flow
		}
		p := dfs(tr, t, push)
		if p == 0 {
			continue
		}
		graph[v][i].flow += p
		graph[tr][edge.rev].flow -= p
		return p
	}
	return 0
}

func dinic(s, t int) int {
	flow := 0
	for bfs(s, t) {
		for i := range ptr {
			ptr[i] = 0
		}
		for {
			pushed := dfs(s, t, INF)
			if pushed == 0 {
				break
			}
			flow += pushed
		}
	}
	return flow
}

func main() {
	scanner = bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	buf := make([]byte, 1024*1024)
	scanner.Buffer(buf, 1024*1024)

	if !scanner.Scan() {
		return
	}
	n, _ := strconv.Atoi(scanner.Text())
	m := nextInt()

	s := make([]int, n+1)
	for i := 1; i <= n; i++ {
		s[i] = nextInt()
	}

	a := make([]int, n+1)
	for i := 1; i <= n; i++ {
		a[i] = nextInt()
	}

	type InputEdge struct {
		u, v     int
		from, to int
		idx      int
	}

	inputEdges := make([]InputEdge, m)
	initialB := make([]int, n+1)

	graph = make([][]Edge, n+4)
	level = make([]int, n+4)
	ptr = make([]int, n+4)

	for i := 0; i < m; i++ {
		u := nextInt()
		v := nextInt()
		inputEdges[i] = InputEdge{u: u, v: v}
		initialB[u]--
		initialB[v]++

		from := v
		to := u
		inputEdges[i].from = from
		inputEdges[i].to = to
		inputEdges[i].idx = len(graph[from])
		addEdge(from, to, 1)
	}

	R := n + 1
	SS := n + 2
	TT := n + 3

	reqFlow := 0
	balR := 0
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	for i := 1; i <= n; i++ {
		if s[i] == 1 {
			diff := a[i] - initialB[i]
			if diff < 0 {
				diff = -diff
			}
			if diff%2 != 0 {
				fmt.Fprintln(writer, "NO")
				return
			}
			bal := (initialB[i] - a[i]) / 2
			if bal > 0 {
				addEdge(SS, i, bal)
				reqFlow += bal
			} else if bal < 0 {
				addEdge(i, TT, -bal)
			}
			balR -= bal
		} else {
			addEdge(i, R, INF)
			addEdge(R, i, INF)
		}
	}

	if balR > 0 {
		addEdge(SS, R, balR)
		reqFlow += balR
	} else if balR < 0 {
		addEdge(R, TT, -balR)
	}

	maxFlow := dinic(SS, TT)

	if maxFlow != reqFlow {
		fmt.Fprintln(writer, "NO")
	} else {
		fmt.Fprintln(writer, "YES")
		for i := 0; i < m; i++ {
			from := inputEdges[i].from
			idx := inputEdges[i].idx
			if graph[from][idx].flow > 0 {
				fmt.Fprintf(writer, "%d %d\n", inputEdges[i].v, inputEdges[i].u)
			} else {
				fmt.Fprintf(writer, "%d %d\n", inputEdges[i].u, inputEdges[i].v)
			}
		}
	}
}