← Home
```go
package main

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

var scanner *bufio.Scanner

func init() {
	scanner = bufio.NewScanner(os.Stdin)
	scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024)
	scanner.Split(bufio.ScanWords)
}

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

func main() {
	n := nextInt()
	m := nextInt()
	r := nextInt()
	b := nextInt()

	color1 := byte('r')
	color2 := byte('b')
	if r > b {
		r, b = b, r
		color1, color2 = color2, color1
	}

	X := make([]int, n)
	Y := make([]int, n)
	x_map := make(map[int]int)
	y_map := make(map[int]int)
	N_X := 0
	N_Y := 0

	for i := 0; i < n; i++ {
		X[i] = nextInt()
		Y[i] = nextInt()
		if _, ok := x_map[X[i]]; !ok {
			N_X++
			x_map[X[i]] = N_X
		}
		if _, ok := y_map[Y[i]]; !ok {
			N_Y++
			y_map[Y[i]] = N_Y
		}
	}

	cnt_X := make([]int, N_X+1)
	cnt_Y := make([]int, N_Y+1)
	for i := 0; i < n; i++ {
		cnt_X[x_map[X[i]]]++
		cnt_Y[y_map[Y[i]]]++
	}

	d_X := make([]int, N_X+1)
	d_Y := make([]int, N_Y+1)
	for i := 1; i <= N_X; i++ {
		d_X[i] = 1e9
	}
	for i := 1; i <= N_Y; i++ {
		d_Y[i] = 1e9
	}

	for i := 0; i < m; i++ {
		t := nextInt()
		l := nextInt()
		d := nextInt()
		if t == 1 {
			if id, ok := x_map[l]; ok {
				if d < d_X[id] {
					d_X[id] = d
				}
			}
		} else {
			if id, ok := y_map[l]; ok {
				if d < d_Y[id] {
					d_Y[id] = d
				}
			}
		}
	}

	S := 0
	T := N_X + N_Y + 1
	S_prime := T + 1
	T_prime := T + 2
	num_nodes := T_prime + 1

	head := make([]int, num_nodes)
	for i := range head {
		head[i] = -1
	}
	type Edge struct {
		to, cap, flow, next int
	}
	edges := make([]Edge, 0)
	add_edge := func(u, v, cap int) {
		edges = append(edges, Edge{v, cap, 0, head[u]})
		head[u] = len(edges) - 1
		edges = append(edges, Edge{u, 0, 0, head[v]})
		head[v] = len(edges) - 1
	}

	demand := make([]int, num_nodes)
	add_demand_edge := func(u, v, L, R int) {
		add_edge(u, v, R-L)
		demand[v] += L
		demand[u] -= L
	}

	for i := 1; i <= N_X; i++ {
		L := 0
		if cnt_X[i] > d_X[i] {
			L = (cnt_X[i] - d_X[i] + 1) / 2
		}
		R := (cnt_X[i] + d_X[i]) / 2
		if R > cnt_X[i] {
			R = cnt_X[i]
		}
		if L > R {
			fmt.Println("-1")
			return
		}
		add_demand_edge(S, i, L, R)
	}

	for i := 1; i <= N_Y; i++ {
		L := 0
		if cnt_Y[i] > d_Y[i] {
			L = (cnt_Y[i] - d_Y[i] + 1) / 2
		}
		R := (cnt_Y[i] + d_Y[i]) / 2
		if R > cnt_Y[i] {
			R = cnt_Y[i]
		}
		if L > R {
			fmt.Println("-1")
			return
		}
		add_demand_edge(i+N_X, T, L, R)
	}

	point_edge_idx := make([]int, n)
	for i := 0; i < n; i++ {
		u := x_map[X[i]]
		v := y_map[Y[i]] + N_X
		add_edge(u, v, 1)
		point_edge_idx[i] = len(edges) - 2
	}

	add_edge(T, S, 1e9)
	ts_edge_idx := len(edges) - 2

	sum_demands := 0
	for i := 0; i <= T; i++ {
		if demand[i] > 0 {
			add_edge(S_prime, i, demand[i])
			sum_demands += demand[i]
		} else if demand[i] < 0 {
			add_edge(i, T_prime, -demand[i])
		}
	}

	level := make([]int, num_nodes)
	ptr := make([]int, num_nodes)

	var bfs func(s, t int) bool
	bfs = func(s, t int) bool {
		for i := range level {
			level[i] = -1
		}
		level[s] = 0
		q := []int{s}
		for len(q) > 0 {
			v := q[0]
			q = q[1:]
			for e := head[v]; e != -1; e = edges[e].next {
				to := edges[e].to
				if edges[e].cap-edges[e].flow > 0 && level[to] == -1 {
					level[to] = level[v] + 1
					q = append(q, to)
				}
			}
		}
		return level[t] != -1
	}

	var dfs func(v, t, pushed int) int
	dfs = func(v, t, pushed int) int {
		if pushed == 0 {
			return 0
		}
		if v == t {
			return pushed
		}
		for ; ptr[v] != -1; ptr[v] = edges[ptr[v]].next {
			e := ptr[v]
			tr := edges[e].to
			if level[v]+1 != level[tr] || edges[e].cap-edges[e].flow == 0 {
				continue
			}
			push := pushed
			if edges[e].cap-edges[e].flow < push {
				push = edges[e].cap - edges[e].flow
			}
			pushed_now := dfs(tr, t, push)
			if pushed_now == 0 {
				continue
			}
			edges[e].flow += pushed_now
			edges[e^1].flow -= pushed_now
			return pushed_now
		}
		return 0
	}

	dinic := func(s, t int) int {
		flow := 0
		for bfs(s, t) {
			copy(ptr, head)
			for {
				pushed := dfs(s, t, 1e9)
				if pushed == 0 {
					break
				}
				flow += pushed
			}
		}
		return flow
	}

	if dinic(S_prime, T_prime) != sum_demands {
		fmt.Println("-1")
		return
	}

	edges[ts_edge_idx].cap = 0
	edges[ts_edge_idx].flow = 0
	edges[ts_edge_idx^1].cap = 0
	edges[ts_edge_idx^1].flow = 0

	for i := ts_edge_idx + 2; i < len(edges); i++ {
		edges[i].cap = 0
		edges[i].flow = 0
	}

	dinic(S, T)

	red_count := 0
	res_str := make([]byte, n)
	for i := 0; i < n; i++ {
		if edges[point_edge_idx[i]].flow == 1 {
			red_count++
			res_str[i] = color1
		} else {
			res_str[i] = color2
		}
	}

	ans_cost := int64(red_count)*int64(r) + int64(n-red_count)*int64(b)
	fmt.Println(ans_cost)
	fmt.Println(string(res_str))
}
```