假设
r≤b
r
≤
b
。
把每一行作为左边的点,每一列作为右边的点建一张二分图。
每个点在对应的行列间连边,流量上限为
1
1
。这条边流量为 表示选红色,否则表示选蓝色。
对于左边的一个点,设右边与它相邻的点数为
s
s
,它的限制为 ,那么通过这个结点的流量
f
f
满足
s−d2≤f≤s+d2
s
−
d
2
≤
f
≤
s
+
d
2
右边同理。
由于 r≤b r ≤ b ,红色选得越多越好,所以跑一遍有上下界最大流就好了。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> abcd;
#define fi first
#define se second
const int N=200010;
const int M=5000000;
const int INF=1e9;
map<int,int>f1,f2;
abcd a[N],b[N],A[N];
int cnt1,cnt2,R,B;
int num=1,h[N],cur[N],nx[M],t[M],c[M];
int k,n,m;
int mn1[N],mn2[N],tot1[N],tot2[N];
int d[N],w[N],sum;
int dis[N],q[N],l,r;
int S,T,SS,TT;
bool fl;
inline void Add(int x,int y,int z){
if(!z)return;
t[++num]=y;nx[num]=h[x];h[x]=num;c[num]=z;
t[++num]=x;nx[num]=h[y];h[y]=num;c[num]=0;
}
inline void Add(int x,int y,int l,int r){
Add(x,y,r-l);d[x]-=l;d[y]+=l;
}
inline void Build(){
TT=T+1;
for(int i=S;i<=T;i++)
if(d[i]>0)Add(SS,i,d[i]),sum+=d[i];else Add(i,TT,-d[i]);
}
inline bool Bfs(int S,int T){
memset(dis,127,sizeof(dis));
l=0;q[r=1]=S;dis[S]=0;
while(++l<=r){
int x=q[l];
for(int i=h[x];i;i=nx[i])
if(c[i]&&dis[t[i]]>dis[x]+1)dis[t[i]]=dis[x]+1,q[++r]=t[i];
}
return dis[T]<INF;
}
int Dfs(int x,int T,int f){
if(x==T)return f;
int sum=0,tmp;
for(int& i=cur[x];i;i=nx[i])
if(c[i]&&dis[t[i]]==dis[x]+1&&(tmp=Dfs(t[i],T,min(f,c[i])))){
f-=tmp;sum+=tmp;
c[i]-=tmp;c[i^1]+=tmp;
if(!f)break;
}
return sum;
}
inline int Dinic(int s,int t){
int Ans=0;
while(Bfs(s,t)){
for(int i=s;i<=t;i++)cur[i]=h[i];
Ans+=Dfs(s,t,INF);
}
return Ans;
}
inline void Solve(){
Build();
Add(T,S,INF);
int t=Dinic(SS,TT);
if(t!=sum){
puts("-1");
return;
}
t=Dinic(S,T);
printf("%I64d\n",1ll*t*R+1ll*(n-t)*B);
for(int i=1;i<=n;i++){
int tmp=c[w[i]];
if(tmp^fl)putchar('b');else putchar('r');
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&R,&B);
if(R>B)swap(R,B),fl=1;
for(int i=1;i<=n;i++)scanf("%d%d",&a[i].fi,&b[i].fi),a[i].se=b[i].se=i;
sort(a+1,a+n+1);sort(b+1,b+n+1);
for(int i=1;i<=n;i++){
if(a[i].fi!=a[i-1].fi)f1[a[i].fi]=++cnt1;
A[a[i].se].fi=cnt1;tot1[cnt1]++;
if(b[i].fi!=b[i-1].fi)f2[b[i].fi]=++cnt2;
A[b[i].se].se=cnt2;tot2[cnt2]++;
}
for(int i=1;i<=cnt1;i++)mn1[i]=tot1[i];
for(int i=1;i<=cnt2;i++)mn2[i]=tot2[i];
S=1;T=cnt1+cnt2+2;
for(int i=1;i<=n;i++)Add(A[i].fi+1,A[i].se+cnt1+1,1),w[i]=num-1;
for(int i=1;i<=m;i++){
int t,l,d;
scanf("%d%d%d",&t,&l,&d);
if(t==1){
if(!f1.count(l))continue;
l=f1[l];
mn1[l]=min(mn1[l],d);
}else{
if(!f2.count(l))continue;
l=f2[l];
mn2[l]=min(mn2[l],d);
}
}
for(int i=1;i<=cnt1;i++){
if(!mn1[i]&&tot1[i]&1){
puts("-1");
return 0;
}
Add(S,i+1,(tot1[i]-mn1[i]+1)/2,(tot1[i]+mn1[i])/2);
}
for(int i=1;i<=cnt2;i++){
Add(i+cnt1+1,T,(tot2[i]-mn2[i]+1)/2,(tot2[i]+mn2[i])/2);
if(!mn2[i]&&tot2[i]&1){
puts("-1");
return 0;
}
}
Solve();
return 0;
}