jly 的模板
c++
struct MCFGraph {
struct Edge {
int v, c, f;
Edge(int v, int c, int f) : v(v), c(c), f(f) {}
};
const int n;
std::vector<Edge> e;
std::vector<std::vector<int>> g;
std::vector<i64> h, dis;
std::vector<int> pre;
bool dijkstra(int s, int t) {
dis.assign(n, std::numeric_limits<i64>::max());
pre.assign(n, -1);
std::priority_queue<std::pair<i64, int>, std::vector<std::pair<i64, int>>, std::greater<std::pair<i64, int>>> que;
dis[s] = 0;
que.emplace(0, s);
while (!que.empty()) {
i64 d = que.top().first;
int u = que.top().second;
que.pop();
if (dis[u] < d) continue;
for (int i : g[u]) {
int v = e[i].v;
int c = e[i].c;
int f = e[i].f;
if (c > 0 && dis[v] > d + h[u] - h[v] + f) {
dis[v] = d + h[u] - h[v] + f;
pre[v] = i;
que.emplace(dis[v], v);
}
}
}
return dis[t] != std::numeric_limits<i64>::max();
}
MCFGraph(int n) : n(n), g(n) {}
void addEdge(int u, int v, int c, int f) {
if (f < 0) {
g[u].push_back(e.size());
e.emplace_back(v, 0, f);
g[v].push_back(e.size());
e.emplace_back(u, c, -f);
} else {
g[u].push_back(e.size());
e.emplace_back(v, c, f);
g[v].push_back(e.size());
e.emplace_back(u, 0, -f);
}
}
std::pair<int, i64> flow(int s, int t) {
int flow = 0;
i64 cost = 0;
h.assign(n, 0);
while (dijkstra(s, t)) {
for (int i = 0; i < n; ++i) h[i] += dis[i];
int aug = std::numeric_limits<int>::max();
for (int i = t; i != s; i = e[pre[i] ^ 1].v) aug = std::min(aug, e[pre[i]].c);
for (int i = t; i != s; i = e[pre[i] ^ 1].v) {
e[pre[i]].c -= aug;
e[pre[i] ^ 1].c += aug;
}
flow += aug;
cost += i64(aug) * h[t];
}
return std::make_pair(flow, cost);
}
};
最大流最小费模板
在 2850. 将石头分散到网格图的最少移动次数 2896. 执行操作使两个字符串相等 都可以用这个模板过,设置好虚拟源点和终点(max 编号+1),搞清楚加边的容量和费用,套进去就可以了,目前看来都是用在二分图上(搞清楚题目能不能转化为二分图)
c++
template<typename K>
class MCMF {
// he: 头 ne: 链表 e: 终点 cap: 容量 dep: 分层 cur: 当前弧
vector<int> he, ne, e, vis, cur, inq;
vector<K> cap, cost, dis;
int n, m, S, T;
K INF;
public:
MCMF(int n_, int S_, int T_) : n(n_), S(S_), T(T_) {
memset(&INF, 0x3f, sizeof INF);
he.resize(n, -1);
dis.resize(n);
inq.resize(n);
vis.resize(n, 0);
cur.resize(n);
}
/**
* @param w 容量
* @param c 费用
*/
void addEdge(int a, int b, K _cap, K _cost) {
cap.emplace_back(_cap), cost.emplace_back(_cost);
ne.emplace_back(he[a]), he[a] = e.size(), e.emplace_back(b);
cap.emplace_back(0), cost.emplace_back(-_cost);
ne.emplace_back(he[b]), he[b] = e.size(), e.emplace_back(a);
}
bool spfa() {
queue<int> q({S});
fill(begin(dis), end(dis), INF);
fill(begin(inq), end(inq), 0);
cur = he;
dis[S] = 0, cur[S] = he[S], inq[S] = 1;
while (!q.empty()) {
int u = q.front();
q.pop();
inq[u] = 0;
for (auto i = he[u]; ~i; i = ne[i]) {
int v = e[i];
if (cap[i] && dis[u] + cost[i] < dis[v]) {
dis[v] = dis[u] + cost[i];
if (!inq[v]) {
q.emplace(v);
inq[v] = 1;
}
}
}
}
return dis[T] != INF;
}
K find(int u, K limit) {
if (u == T)
return limit;
vis[u] = 1;
K flow = 0;
for (auto i = cur[u]; ~i && flow < limit; i = ne[i]) {
cur[u] = i;
int v = e[i];
if (!vis[v] && cap[i] && dis[v] == dis[u] + cost[i]) {
K t = find(v, min(cap[i], limit - flow));
cap[i] -= t, cap[i ^ 1] += t, flow += t;
}
}
vis[u] = 0;
return flow;
}
pair<K, K> run() {
K maxflow = 0, mincost = 0;
while (spfa()) {
K t = find(S, INF);
maxflow += t;
mincost += t * dis[T];
}
return {maxflow, mincost};
}
};
// 2896
class Solution {
public:
int minOperations(string s1, string s2, int x) {
int n = s1.size();
vector<int> p;
for (int i = 0; i < n; i++)
if (s1[i] != s2[i]) p.push_back(i);
int m = p.size();
if (m % 2) return -1;
int src = m, dst = m + 1;
MCMF<int> mcf(n + 2, src, dst);
for (int i = 0; i < m; i++)
if (i % 2 == 0) mcf.addEdge(src, i, 1, 0);
else mcf.addEdge(i, dst, 1, 0);
for (int i = 0; i < m; i += 2)
for (int j = 1; j < m; j += 2)
mcf.addEdge(i, j, 1, min(abs(p[j] - p[i]), x));
return mcf.run().second;
}
};
// 2850
class Solution {
public:
int minimumMoves(vector<vector<int>>& g) {
int S = 18, T = 19;
MCMF<int> mcf(20, S, T);
int id = 0;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
mcf.addEdge(i * 3 + j + 9, T, 1, 0);
for (int k = 0; k < g[i][j]; ++k, ++id) {
mcf.addEdge(S, id, 1, 0);
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
int t = x * 3 + y + 9;
mcf.addEdge(id, t, 1, abs(x - i) + abs(y - j));
}
}
}
}
}
return mcf.run().second;
}
};