[CF Edu 80] Red-Blue Graph

题目: [CF Edu 80] Red-Blue Graph

链接:https://codeforces.com/contest/1288/problem/F

分析:

原来在费用流里必选一条边还能用-inf来控制,原谅我孤陋寡闻了

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 410;
const int MAXM = MAXN * 10;
const int inf = 1e6;
const LL INF = 1e18;
namespace NWF{
    struct Edge {
        int to, nxt;LL f, c;
    } e[MAXM << 1]; 
    int S, T, tot;
    int ecnt, head[MAXN], cur[MAXN];LL dis[MAXN];
    bool exist[MAXN];
    queue<int> q;
    void init(int _S, int _T, int _tot){
        ecnt = 1; S = _S; T = _T; tot = _tot;
        memset(head, 0, (tot + 1) * sizeof(int));
    } 
    void addEdge(int u, int v, LL f, LL c) {
        e[++ecnt] = (Edge) {v, head[u], f, c}; head[u] = ecnt;
        e[++ecnt] = (Edge) {u, head[v], 0,-c}; head[v] = ecnt;
    }
    bool spfa() {
        for(int i = 0;i <= tot; ++i){
            dis[i] = INF; cur[i] = exist[i] = 0;
        }
        q.push(S);dis[S] = 0;exist[S] = 1;
        while(!q.empty()) {
            int u = q.front(), v; q.pop();exist[u] = 0;
            for(int i = head[u]; i; i = e[i].nxt) {
                if(e[i].f && dis[v = e[i].to] > dis[u] + e[i].c) {
                    dis[v] = dis[u] + e[i].c;
                    cur[v] = i;
                    if(!exist[v]) {
                        q.push(v);
                        exist[v] = 1;
                    }
                }
            }
        }
        return dis[T] != INF;
    }
    LL mcmf() {
        LL cost = 0;
        while(spfa() && dis[T] < 0) {
            LL flow = INF;
            for(int i = T; i != S; i = e[cur[i] ^ 1].to)
                flow = min(flow, e[cur[i]].f);
            for(int i = T; i != S; i = e[cur[i] ^ 1].to) {
                e[cur[i]].f -= flow;
                e[cur[i] ^ 1].f += flow;
            }
            cost += flow * dis[T];
        }
        return cost;
    }
}
int msk[MAXN];
int main() {
    int n1, n2, m, r, b, cnt = 0;
    cin >> n1 >> n2 >> m >> r >> b;
    string col1, col2;
    cin >> col1;
    NWF::init(0, n1 + n2 + 1, n1 + n2 + 2);
    for(int i = 1; i <= n1; i++) {
        if(col1[i-1]=='R') NWF::addEdge(NWF::S, i, 1, -inf) , cnt++;
        if(col1[i-1]=='B') NWF::addEdge(i, NWF::T, 1, -inf) , cnt++;
        if(col1[i-1]!='B') NWF::addEdge(NWF::S, i, inf, 0);
        if(col1[i-1]!='R') NWF::addEdge(i, NWF::T, inf, 0);
    }
    cin >> col2; 
    for(int i = 1; i <= n2; i++) {
        if(col2[i-1]=='R') NWF::addEdge(i+n1, NWF::T, 1, -inf), cnt++;
        if(col2[i-1]=='B') NWF::addEdge(NWF::S, i+n1, 1, -inf), cnt++;
        if(col2[i-1]!='B') NWF::addEdge(i+n1,NWF::T, inf, 0);
        if(col2[i-1]!='R') NWF::addEdge(NWF::S,i+n1, inf, 0);
    }
    for(int i = 1, u, v; i <= m; i++) {
        cin >> u >> v; v += n1;
        NWF::addEdge(u, v, 1, r);
        NWF::addEdge(v, u, 1, b);
        msk[i] = NWF::ecnt - 3;
    }
    LL ans = NWF::mcmf()+(LL)cnt*inf;
    if(ans >= inf) cout << "-1" <<endl;
    else{
        cout << ans << endl;
        for(int i = 1; i <= m; i++)
            cout << (NWF::e[msk[i]].f == 0 ?'R': NWF::e[msk[i]+2].f==0?'B':'U');
        printf("
");
    }
    return 0;
}

上下界网络流

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 410;
const int MAXM = MAXN * 10;
const int inf = 1e6;
const LL INF = 1e18;
namespace NWF{
    struct Edge {
        int to, nxt;LL f, c;
    } e[MAXM << 1]; 
    int S, T, tot;
    int ecnt, head[MAXN], cur[MAXN];LL dis[MAXN];
    bool exist[MAXN];
    queue<int> q;
    void init(int _S, int _T, int _tot){
        ecnt = 1; S = _S; T = _T; tot = _tot;
        memset(head, 0, (tot + 1) * sizeof(int));
    } 
    void addEdge(int u, int v, LL f, LL c) {
        e[++ecnt] = (Edge) {v, head[u], f, c}; head[u] = ecnt;
        e[++ecnt] = (Edge) {u, head[v], 0,-c}; head[v] = ecnt;
    }
    bool spfa() {
        for(int i = 0;i <= tot; ++i){
            dis[i] = INF; cur[i] = exist[i] = 0;
        }
        q.push(S);dis[S] = 0;exist[S] = 1;
        while(!q.empty()) {
            int u = q.front(), v; q.pop();exist[u] = 0;
            for(int i = head[u]; i; i = e[i].nxt) {
                if(e[i].f && dis[v = e[i].to] > dis[u] + e[i].c) {
                    dis[v] = dis[u] + e[i].c;
                    cur[v] = i;
                    if(!exist[v]) {
                        q.push(v);
                        exist[v] = 1;
                    }
                }
            }
        }
        return dis[T] != INF;
    }
    LL mcmf() {
        LL cost = 0;
        while(spfa()) {
            LL flow = INF;
            for(int i = T; i != S; i = e[cur[i] ^ 1].to)
                flow = min(flow, e[cur[i]].f);
            for(int i = T; i != S; i = e[cur[i] ^ 1].to) {
                e[cur[i]].f -= flow;
                e[cur[i] ^ 1].f += flow;
            }
            cost += flow * dis[T];
        }
        return cost;
    }
    bool check() {
        for(int i = head[S]; i; i = e[i].nxt) {
            if(e[i].f)return true;
        }
        return false;
    }
}
int msk[MAXN];
int main() {
    int n1, n2, m, r, b;
    cin >> n1 >> n2 >> m >> r >> b;
    string col1, col2;
    cin >> col1;
    int CS = 0, CT = n1+n2+1, outCS = 0, inCT = 0;
    NWF::init(CT+1, CT+2, CT + 3);
    for(int i = 1; i <= n1; i++) {
        if(col1[i-1]=='R') {
            NWF::addEdge(NWF::S, i, 1, 0);
            NWF::addEdge(CS, i, inf, 0);
            ++outCS;
        }
        if(col1[i-1]=='B') {
            NWF::addEdge(i, NWF::T, 1, 0);
            NWF::addEdge(i, CT, inf, 0);
            ++inCT;
        }
        if(col1[i-1]=='U') {
            NWF::addEdge(CS, i, inf, 0);
            NWF::addEdge(i, CT, inf, 0);
        }
    }
    cin >> col2; 
    for(int i = 1; i <= n2; i++) {
        if(col2[i-1]=='R') {
            NWF::addEdge(i+n1, NWF::T, 1, 0);
            NWF::addEdge(i+n1, CT, inf, 0);
            ++inCT;
        }
        if(col2[i-1]=='B') {
            NWF::addEdge(NWF::S, i+n1, 1, 0);
            NWF::addEdge(CS, i+n1, inf, 0);
            ++outCS;
        }
        if(col2[i-1]=='U') {
            NWF::addEdge(i+n1,CT, inf, 0);
            NWF::addEdge(CS,i+n1, inf, 0);
        }
    }
    NWF::addEdge(CT, CS, inf, 0);
    NWF::addEdge(NWF::S, CT, inCT, 0);
    NWF::addEdge(CS, NWF::T, outCS, 0);
    for(int i = 1, u, v; i <= m; i++) {
        cin >> u >> v; v += n1;
        NWF::addEdge(u, v, 1, r);
        NWF::addEdge(v, u, 1, b);
        msk[i] = NWF::ecnt - 3;
    }
    LL ans = NWF::mcmf();
    if(NWF::check()) cout << "-1" <<endl;
    else{
        cout << ans << endl;
        for(int i = 1; i <= m; i++)
            cout << (NWF::e[msk[i]].f == 0 ?'R': NWF::e[msk[i]+2].f==0?'B':'U');
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hjj1871984569/p/12235383.html