题目: [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; }