4514: [Sdoi2016]数字配对

来源:互联网 发布:java命令运行class 编辑:程序博客网 时间:2024/05/29 18:55

4514: [Sdoi2016]数字配对

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1801  Solved: 683
[Submit][Status][Discuss]

Description

有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,
那么这两个数字可以配对,并获得 ci×cj 的价值。
一个数字只能参与一次配对,可以不参与配对。
在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。

Input

第一行一个整数 n。
第二行 n 个整数 a1、a2、……、an。
第三行 n 个整数 b1、b2、……、bn。
第四行 n 个整数 c1、c2、……、cn。

Output

 一行一个数,最多进行多少次配对

Sample Input

3
2 4 8
2 200 7
-1 -2 1

Sample Output

4

HINT

 n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5


#include<stdio.h>#include<algorithm>#include<queue>#include<string.h>#include<math.h>using namespace std;#define ll long longconst ll maxm = 10005;const ll INF = 10000000000000LL;struct node{ll u, v, flow, cost, next;}edge[maxm];ll vis[maxm], pre[maxm], head[maxm];ll dis[maxm], a[maxm], b[maxm], c[maxm], ans = 0;ll n, m, s, t, cnt;void init(){cnt = 0, s = 0, t = n * 2 + 1, ans = 0;memset(head, -1, sizeof(head));}void add(ll u, ll v, ll flow, long long cost){edge[cnt].u = u, edge[cnt].v = v;edge[cnt].flow = flow, edge[cnt].cost = cost;edge[cnt].next = head[u], head[u] = cnt++;edge[cnt].u = v, edge[cnt].v = u;edge[cnt].flow = 0, edge[cnt].cost = -cost;edge[cnt].next = head[v], head[v] = cnt++;}ll bfs(){queue<ll>q;for (ll i = 0;i <= t;i++) dis[i] = -INF;memset(pre, -1, sizeof(pre));dis[s] = 0;q.push(s);while (!q.empty()){ll u = q.front();q.pop();for (ll i = head[u];i != -1;i = edge[i].next){ll v = edge[i].v;if (dis[v] < dis[u] + edge[i].cost&&edge[i].flow){dis[v] = dis[u] + edge[i].cost;pre[v] = i;q.push(v);}}}//printf("%lld %lld\n", dis[t], ans);if (ans + dis[t] >= 0) return 1;return 0;}ll MCMF(){ll flow = 0, minflow;while (bfs()){minflow = INF;if (dis[t] < 0) minflow = ans / -dis[t];for (ll i = pre[t];i != -1;i = pre[edge[i].u])minflow = min(minflow, edge[i].flow);for (ll i = pre[t];i != -1;i = pre[edge[i].u]){edge[i].flow -= minflow;edge[i ^ 1].flow += minflow;}ans += dis[t] * minflow, flow += minflow;}return flow;}bool judge(ll x, ll y){if (y == 0 || a[x] % a[y] != 0) return false;long long xx = a[x] / a[y];if (xx < 2) return false;if (xx == 2) return true;ll k = sqrt(xx);for (ll i = 2;i <= k;i++)if (xx%i == 0) return false;return true;}int main(){ll i, j, k, sum;scanf("%lld", &n);init();for (i = 1;i <= n;i++)scanf("%lld", &a[i]);for (i = 1;i <= n;i++)scanf("%lld", &b[i]);for (i = 1;i <= n;i++)scanf("%lld", &c[i]);for (i = 1;i <= n;i++){add(s, i, b[i], 0);add(i + n, t, b[i], 0);}for (i = 1;i <= n;i++){for (j = 1;j <= n;j++){if (i == j) continue;if (judge(i, j)) add(i, j + n, INF, c[i] * c[j]);if (judge(j, i)) add(i, j + n, INF, c[i] * c[j]);}}printf("%lld\n", MCMF() / 2);return 0;}