CF1288F Red-Blue Graph

https://www.luogu.com.cn/problem/CF1288F

对于原图中的每一条边 ( u , v ) (u,v) (u,v)
考虑拆成两条边 ( u , v , 0 , 1 , R ) , ( v , u , 0 , 1 , B ) (u, v, 0, 1, R), (v, u, 0, 1, B) (u,v,0,1,R),(v,u,0,1,B)
如果这一条边是从左往右流的,那么就是红边,右往左就是蓝边

然后对于左边的红点和右边的蓝点,出流应当大于入流,连边 ( S , x , 1 , i n f , 0 ) (S, x, 1, inf, 0) (S,x,1,inf,0)
对于左边的蓝点和右边的红点,入流应当大于出流,连边 ( x , T , 1 , i n f , 0 ) (x, T, 1, inf, 0) (x,T,1,inf,0)

无色点就直接连边 ( S , x , 0 , i n f , 0 ) 和 ( x , T , 0 , i n f , 0 ) (S,x,0,inf,0)和(x,T,0,inf,0) (S,x,0,inf,0)(x,T,0,inf,0)即可

code:

#include<bits/stdc++.h>
#define N 200500
using namespace std;
struct edge {
    int v, nxt, c, w;
} e[N << 1];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
void insert(int u, int v, int c, int w) {
    e[eid].v = v;
    e[eid].nxt = p[u];
    e[eid].c = c;
    e[eid].w = w;
    p[u] = eid ++;
}
void add(int u, int v, int c, int w) {// if(c) printf("%d --> %d %d %d\n", u, v, c, w);
    insert(u, v, c, w), insert(v, u, 0, -w);
}
queue<int> q;
int dis[N], pre[N], vis[N], S, T;
const int INF = 1e9;
int bfs() {
    for(int i = 0; i <= T; i ++) dis[i] = INF, vis[i] = 0, pre[i] = -1;
    dis[S] = 0; q.push(S);
    while(q.size()) {
        int u = q.front(); q.pop();
        vis[u] = 0;
        for(int i = p[u]; i + 1; i = e[i].nxt) {
            int v = e[i].v;
            if(e[i].c && dis[u] + e[i].w < dis[v]) {
                dis[v] = dis[u] + e[i].w;
                pre[v] = i;
                if(!vis[v]) vis[v] = 1, q.push(v);
            }
        }
    }
    return pre[T] != -1;
}
int totc, totw, sum[N], n1, n2, m, SS, TT, R, B, pr[N], pb[N];
int mcfc() {
    int ret = 0;
    for(; bfs() ; ) {
        int flow = INF;
        for(int i = T; i != S; i = e[pre[i] ^ 1].v) flow = min(flow, e[pre[i]].c);
        ret += flow;
        for(int i = T; i != S; i = e[pre[i] ^ 1].v) {
            totw += flow * e[pre[i]].w;
            e[pre[i]].c -= flow, e[pre[i] ^ 1].c += flow;
        }
    }
    return ret;
}
void addl(int u, int v, int l, int r, int w) {
    if(l < r) add(u, v, r - l, w);
    sum[u] -= l, sum[v] += l; totw += l * w;
}
void build() {
    for(int i = 1; i <= TT; i ++) {
        if(sum[i] > 0) totc += sum[i], add(S, i, sum[i], 0);
        if(sum[i] < 0) add(i, T, -sum[i], 0);
    } add(TT, SS, INF, 0);
}
int main() {
    
    init();
    scanf("%d%d%d%d%d", &n1, &n2, &m, &R, &B);
    SS = n1 + n2 + 1, TT = SS + 1, S = TT + 1, T = S + 1;
    
    for(int i = 1; i <= n1; i ++) {
        char ch;
        scanf(" %c", &ch);
        if(ch == 'R') addl(SS, i, 1, INF, 0);
        if(ch == 'B') addl(i, TT, 1, INF, 0);
        if(ch == 'U') addl(SS, i, 0, INF, 0), addl(i, TT, 0, INF, 0);
    }
    for(int i = n1 + 1; i <= n1 + n2; i ++) {
        char ch;
        scanf(" %c", &ch);
        if(ch == 'B') addl(SS, i, 1, INF, 0);
        if(ch == 'R') addl(i, TT, 1, INF, 0);
        if(ch == 'U') addl(SS, i, 0, INF, 0), addl(i, TT, 0, INF, 0);
    }
    for(int i = 1; i <= m; i ++) {
        int u, v;
        scanf("%d%d", &u, &v);
        addl(u, v + n1, 0, 1, R), pr[i] = eid - 1;
        addl(v + n1, u, 0, 1, B), pb[i] = eid - 1;
    }
    build(); //mcfc();
    //printf("* %d %d\n", mcfc(), totc);
    if(mcfc() < totc) printf("-1");
    else {
        printf("%d\n", totw);
        for(int i = 1; i <= m; i ++) {
            if(e[pr[i]].c) putchar('R');
            else if(e[pb[i]].c) putchar('B');
            else putchar('U');
        }
    }
    return 0;
}


邻接链表写是我没想到的

posted @ 2021-09-27 17:23  lahlah  阅读(26)  评论(0编辑  收藏  举报