最大费用最大流模板(注意和最小的区别仅仅是每条边cost取负,然后最后答案取负)
c
int n, m, u, S, T, Ans, cnt, Sum;
int dis[N], x, h[N], cur[N]; bool vis[N];
struct edge { int to, flow, cost, rev; };
vector <edge> G[N];
struct node {
int x, dis;
friend bool operator < (node a, node b) { return a.dis > b.dis; }
};
void ins(int x, int y, int w, int l) {
G[x].pb({y, w, -l, G[y].size()}); // 最大费用最大流模板,这里要改成-l ,下面是+l,然后最后答案取负即可。
G[y].pb({x, 0, l, G[x].size() - 1});
}
bool dij() {
priority_queue <node> Q;
F(i, 1, cnt) dis[i] = inf; dis[S] = 0; Q.push({S, 0});
while (Q.size()) {
node s = Q.top(); Q.pop();
int k = s.x, v = s.dis;
if (v > dis[k]) continue;
for (auto e : G[k])
if (e.flow && dis[e.to] > dis[k] + e.cost + h[k] - h[e.to]) {
dis[e.to] = dis[k] + e.cost + h[k] - h[e.to];
Q.push({e.to, dis[e.to]});
}
}
return dis[T] < inf;
}
int DFS(int k, int flow) {
if (k == T) return flow;
int have = 0;
vis[k] = 1;
for (int &i = cur[k]; i < G[k].size(); i ++) {
edge &e = G[k][i];
if (!vis[e.to] && e.flow && dis[e.to] == dis[k] + e.cost + h[k] - h[e.to]) {
int now = DFS(e.to, min(flow - have, e.flow));
e.flow -= now, G[e.to][e.rev].flow += now;
have += now;
if (flow == have) break;
}
}
vis[k] = 0;
return have;
}
map <int, int> H; int w[N];
int calc(int x) {
int ans = 0;
for (int y = 2; y * y <= x; y ++)
while (x % y == 0)
x /= y, ans ++;
ans += (x > 1);
return ans;
}
void doit(int x) {
if (!H[x]) {
H[x] = ++ cnt;
ins(cnt, T, 1, 0);
w[cnt] = calc(x);
}
int v = H[x];
ins(u, v, 1, w[u] - w[v]);
}
int main() {
// freopen("data.in","r",stdin);
R(n), S = 1, T = cnt = 2;
F(i, 1, n) {
R(x);
w[u = ++ cnt] = calc(x);
ins(S, u, 1, 0);
for (int j = 1; j * j <= x; j ++) {
if (x % j == 0) {
doit(j);
if (j * j < x)
doit(x / j);
}
}
}
// scanf("%d%d%d%d", &n, &m, &S, &T);
// F(i, 1, m) {
// scanf("%d%d%d%d", &x, &y, &c, &w);
// ins(x, y, c, w);
// }
Ans = 0;
while (dij()) {
F(i, 1, cnt) cur[i] = 0;
int flow = DFS(S, inf);
F(i, 1, cnt) h[i] += dis[i];
Ans += h[T] * flow;
}
printf("%d\n", - Ans);
}
最大流:
c
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i <= (b); ++i)
#define G(i, a, b) for (int i = (a); i >= (b); --i)
#define mem(a, b) memset(a, b, sizeof a)
#define pb push_back
#define putc putchar
#define get getchar()
#define ll long long
#define V vector<int>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
template <typename Int>
void R(Int &x) {
char c = get; x = 0; Int t = 1;
for (; !isdigit(c); c = get) t = (c == '-' ? -1 : t);
for (; isdigit(c); x = (x << 3) + (x << 1) + c - '0', c = get);
x *= t;
}
template <typename Int>
void W(Int x) {
if (x < 0) { putc('-'); x = -x; }
if (x > 9) W(x / 10);
putc(char(x % 10 + '0'));
}
const int INF = 1e9;
int n, m;
ll c, d;
struct Edge { int to, rev, cap; };
int N, S, T;
vector<vector<Edge>> Gg;
V levelv, cur;
int add_edge(int u, int v, int cap) {
Edge a{v, (int)Gg[v].size(), cap};
Edge b{u, (int)Gg[u].size(), 0};
Gg[u].pb(a);
Gg[v].pb(b);
return (int)Gg[u].size() - 1; // 返回 u 侧边下标,便于后续增容
}
bool bfs() {
fill(levelv.begin(), levelv.end(), -1);
queue<int> Q;
levelv[S] = 0; Q.push(S);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
for (auto &e : Gg[u]) if (e.cap > 0 && levelv[e.to] < 0) {
levelv[e.to] = levelv[u] + 1;
Q.push(e.to);
}
}
return levelv[T] >= 0;
}
int dfs(int u, int f) {
if (u == T) return f;
for (int &i = cur[u]; i < (int)Gg[u].size(); ++i) {
Edge &e = Gg[u][i];
if (e.cap > 0 && levelv[e.to] == levelv[u] + 1) {
int ret = dfs(e.to, min(f, e.cap));
if (ret > 0) {
e.cap -= ret;
Gg[e.to][e.rev].cap += ret;
return ret;
}
}
}
return 0;
}
// 在当前残量网络上尽量增广
int maxflow_once() {
int flow = 0, aug;
while (bfs()) {
fill(cur.begin(), cur.end(), 0);
while ((aug = dfs(S, INF)) > 0) flow += aug;
}
return flow;
}
inline void RS(string &s) {
s.clear();
char c = get;
while (isspace(c)) c = get;
for (; !isspace(c); c = get) s.pb(c);
}
int main() {
// 输入
R(n), R(m), R(c), R(d);
vector<string> a(n);
F(i, 0, n - 1) RS(a[i]);
// 统计
vector<int> rowCnt(n, 0), colCnt(m, 0);
int E = 0;
F(i, 0, n - 1) F(j, 0, m - 1)
if (a[i][j] == '.') { ++rowCnt[i]; ++colCnt[j]; ++E; }
int maxRow = 0, maxCol = 0;
F(i, 0, n - 1) maxRow = max(maxRow, rowCnt[i]);
F(j, 0, m - 1) maxCol = max(maxCol, colCnt[j]);
int Delta = max(maxRow, maxCol);
// 建图
S = 0; T = n + m + 1; N = T + 1;
Gg.assign(N, {});
levelv.assign(N, -1);
cur.assign(N, 0);
// 记录源->行 与 列->汇 的边下标,便于逐步增容
V s2r_idx(n), c2t_idx(m);
// 源->行(初始容量0)
F(i, 0, n - 1) s2r_idx[i] = add_edge(S, 1 + i, 0);
// 行->列(空格子为1)
F(i, 0, n - 1) F(j, 0, m - 1)
if (a[i][j] == '.') add_edge(1 + i, 1 + n + j, 1);
// 列->汇(初始容量0)
F(j, 0, m - 1) c2t_idx[j] = add_edge(1 + n + j, T, 0);
ll ans = (ll)4e18;
const ll base = d * 1LL * E; // 常数项
int totalFlow = 0;
// k = 0 的代价
ans = min(ans, base);
// 逐步把每个行/列容量 +1,并在原残量网络上继续增广
F(k, 1, Delta) {
// 行、列容量 +1
F(i, 0, n - 1) Gg[S][ s2r_idx[i] ].cap += 1;
F(j, 0, m - 1) Gg[1 + n + j][ c2t_idx[j] ].cap += 1;
totalFlow += maxflow_once(); // 新能多匹配多少就多送多少
ll cost = base + (c * 1LL * k - d * 1LL * totalFlow);
ans = min(ans, cost);
if (totalFlow == E) break; // 已满匹配,后续只会让 cost 递增 c
}
W(ans), putc('\n');
return 0;
}