[ SDOI2016 ] 数字配对
作者:互联网
题目
思路
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
const int N = 410, M = 200010, INF = 1e18;
int n, m, S, T, A[N], B[N], C[N];
int h[N], val[M], ptr[M], f[M], w[M], idx;
void add(int a, int b, int c, int d) { val[idx] = b, f[idx] = c, w[idx] = d, ptr[idx] = h[a], h[a] = idx++; }
void add(int a, int b, int c, int d, int e) { add(a, b, c, e), add(b, a, d, -e); }
bool check(int x, int y) {
if (x < y) swap(x, y);
if (x % y != 0 || x == y) return false;
int t = x / y;
for (int i = 2; i <= t / i; i++)
if (t % i == 0) return false;
return true;
}
int q[N], d[N], pre[M], incf[N], st[N];
// 最大费用最大流
bool SPFA() {
int hh = 0, tt = 0;
memset(d, -0x3f, sizeof d), memset(incf, 0, sizeof incf);
q[tt++] = S, incf[S] = INF, d[S] = 0, st[S] = true;
while (hh != tt) {
int t = q[hh++];
if (hh == N - 1) hh = 0;
st[t] = false;
for (int i = h[t], v = val[i]; i != -1; i = ptr[i], v = val[i]) {
if (f[i] && d[v] < d[t] + w[i]) {
d[v] = d[t] + w[i], pre[v] = i;
incf[v] = min(incf[t], f[i]);
if (st[v]) continue;
q[tt++] = v, st[v] = true;
if (tt == N - 1) tt = 0;
}
}
}
return incf[T] > 0;
}
int EK() {
int flow = 0, cost = 0;
while (SPFA()) {
int t = incf[T];
if (cost + d[T] * t < 0) {
flow += (cost / (-d[T]));
return flow;
} else cost += d[T] * t, flow += t;
for (int i = T; i != S; i = val[pre[i] ^ 1])
f[pre[i]] -= t, f[pre[i] ^ 1] += t;
}
return flow;
}
signed main() {
cin >> n;
memset(h, -1, sizeof h);
S = 2 * n + 1, T = n * 2 + 2;
for (int i = 1; i <= n; i++) cin >> A[i];
for (int i = 1; i <= n; i++) cin >> B[i];
for (int i = 1; i <= n; i++) cin >> C[i];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (check(A[i], A[j]))
add(i, j + n, INF, 0, C[i] * C[j]);
for (int i = 1; i <= n; i++) add(S, i, B[i], 0, 0);
for (int i = 1; i <= n; i++) add(n + i, T, B[i], 0, 0);
cout << EK() / 2 << endl;
return 0;
}
标签:pre,数字,idx,int,flow,add,cost,SDOI2016,配对 来源: https://www.cnblogs.com/Proteinlzl/p/14878095.html