模板ACM
最大费用最大流模板(注意和最小的区别仅仅是每条边cost取负,然后最后答案取负)
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);
}
最大流:
#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) {// 行、列容量 +1F(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;
}