# 【题解】Red-Blue Graph Codeforces 1288F 上下界费用流

• 从u到v连一条容量是1，费用是r的边，如果走了这条边，意味着这条边染Red。

• 从v到u连一条容量是1，费用是b的边，如果走了这条边，意味着这条边染Blue。

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> pii;
const int N = 210;
int _w;

namespace MCMF {
const int MAXN = 1000010;
const int MAXM = 1000010;

struct Edge {
int u, v, c, f, w;
Edge() {}
Edge( int uu, int vv, int cc, int ff, int ww ) {
u = uu, v = vv, c = cc, f = ff, w = ww;
}
};

int n, m, s, t;
Edge edge[MAXM];

void init( int nn ) {
n = nn, m = 0;
for( int i = 0; i < n; ++i )
}
int adde( int u, int v, int c, int w ) {
int e = m;
edge[m] = Edge(u, v, c, 0, w);
edge[m] = Edge(v, u, 0, 0, -w);
return e;
}

int res[MAXN], from[MAXN];
int dis[MAXN];
bool inq[MAXN];
queue<int> q;

bool spfa() {
for( int i = 0; i < n; ++i )
dis[i] = 1e9;
dis[s] = 0, inq[s] = 1, q.push(s), res[s] = 1e9;
while( !q.empty() ) {
int u = q.front(); q.pop();
inq[u] = 0;
for( int i = head[u]; ~i; i = nxt[i] ) {
Edge &e = edge[i];
if( e.c > e.f && dis[u] + e.w < dis[e.v] ) {
dis[e.v] = dis[u] + e.w;
res[e.v] = min( res[u], e.c-e.f );
from[e.v] = i;
if( !inq[e.v] )
inq[e.v] = 1, q.push(e.v);
}
}
}
return dis[t] != 1e9;
}
void augment() {
int u = t, f = res[t];
while( u != s ) {
int i = from[u];
edge[i].f += f;
edge[i^1].f -= f;
u = edge[i].u;
}
}
pii solve( int ss, int tt ) {
s = ss, t = tt;
int flow = 0;
int cost = 0;
while( spfa() ) {
flow += res[t];
cost += res[t] * dis[t];
augment();
}
return pii(flow, cost);
}
}

int n1, n2, m, r, b;
char Lcolor[N], Rcolor[N], Ecolor[N];
pii edge[N];
int ans;

int S, T, SS, TT, nid, Lid[N], Rid[N];
int eid_red[N], eid_blue[N];

int add_edge( int u, int v, int l, int r, int w ) {
int e = MCMF::adde(u, v, r-l, w);
if( l ) {
}
return e;
}

bool solve() {
S = nid++, T = nid++, SS = nid++, TT = nid++;
for( int i = 1; i <= n1; ++i )
Lid[i] = nid++;
for( int i = 1; i <= n2; ++i )
Rid[i] = nid++;
MCMF::init(nid);
int low_sum = 0;
for( int i = 1; i <= n1; ++i )
if( Lcolor[i] == 'R' ) {
++low_sum;
} else if( Lcolor[i] == 'B' ) {
++low_sum;
} else {
}
for( int i = 1; i <= n2; ++i )
if( Rcolor[i] == 'R' ) {
++low_sum;
} else if( Rcolor[i] == 'B' ) {
++low_sum;
} else {
}
for( int i = 1; i <= m; ++i ) {
int L = edge[i].first;
int R = edge[i].second;
eid_red[i] = add_edge(Lid[L], Rid[R], 0, 1, r);
eid_blue[i] = add_edge(Rid[R], Lid[L], 0, 1, b);
}
pii tmp = MCMF::solve(SS, TT);
if( tmp.first != low_sum ) return false;
ans = tmp.second;
for( int i = 1; i <= m; ++i ) {
using MCMF::edge;
int R = eid_red[i];
int B = eid_blue[i];
if( edge[R].f && !edge[B].f ) {
Ecolor[i] = 'R';
} else if( !edge[R].f && edge[B].f ) {
Ecolor[i] = 'B';
} else {
Ecolor[i] = 'U';
}
}
return true;
}

int main() {
_w = scanf( "%d%d%d%d%d", &n1, &n2, &m, &r, &b );
_w = scanf( "%s", Lcolor+1 );
_w = scanf( "%s", Rcolor+1 );
for( int i = 1; i <= m; ++i ) {
_w = scanf( "%d%d", &edge[i].first, &edge[i].second );
}
if( solve() ) {
printf( "%d\n", ans );
Ecolor[m+1] = 0;
puts(Ecolor + 1);
} else {
puts("-1");
}
return 0;
}


posted @ 2020-01-31 22:00  mlystdcall  阅读(485)  评论(1编辑  收藏  举报