BZOJ 4514: [Sdoi2016] Digital pairing

 

Portal

Is the required maximum number of matches in the case where the charges are not less than zero.

It may be converted to the cost of not greater than 0 (negative charges) maximum matching.

In each spfa resulting cost plus time to determine what is greater than 0, and greater than 0 if you can directly add answers and returned.

#include <bits/stdc++.h>
#define ll long long
using namespace std;

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
    return x * f;
}

const int N = 3e4 + 10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;

struct E { int v, ne, f;  ll c; } e[N];
int head[210], cnt, path[210], n, a[210], b[210];
ll dis[210], c[210];
int pm[32005], pn, si[210], sn, di[210], dn, ans;
bool vis[32005];

inline void add(int u, int v, int f, ll c) {
    e[cnt].v = v; e[cnt].f = f; e[cnt].c = -c; e[cnt].ne = head[u]; head[u] = cnt++;
    e[cnt].v = u; e[cnt].f = 0; e[cnt].c = c; e[cnt].ne = head[v]; head[v] = cnt++;
}

bool spfa(int s, int t) {
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    memset(path, -1, sizeof(path));
    queue<int> que;
    dis[s] = 0;
    while (!que.empty()) que.pop();
    que.push(s);
    vis[s] = true;
    while (!que.empty()) {
        int u = que.front(); que.pop();
        vis[u] = false;
        for (int i = head[u]; ~i; i = e[i].ne) {
            int v = e[i].v, f = e[i].f;
            ll c = e[i].c;
            if (f && dis[v] > dis[u] + c) {
                dis[v] = dis[u] + c;
                path[v] = i;
                if (!vis[v]) {
                    vis[v] = true;
                    que.push(v);
                } 
            }
        }
    }
    return dis[t] != INF;                                               
}

void mcf(int s, int t) {
    ll cost = 0;
    while (spfa(s, t)) {
        int x = inf;
        for (int i = path[t]; ~i; i = path[e[i^1].v]) x = min(x, e[i].f);
        if (cost + dis[t] * x <= 0) {
            cost += dis[t] * x; 
            ans += x;
            for(int i = path[t]; ~i; i = path[e[i^1].v]) e[i].f -= x, e[i^1].f += x;
        } else {
            ans += (-cost) / dis[t];
            return;
        }
    }
}

void gp() {
    for (int i = 2; i <= 32000; i++) {
        if (!vis[i]) pm[++pn] = i;
        for (int j = 1; j <= pn && i * pm[j] <= 32000; j++) {
            vis[i * pm[j]] = true;
            if (i % pm[j] == 0) break;
        }
    } 
}

inline bool check(int x, int y) {
    if (!x || !y) return false;
    if (x < y) swap(x, y);
    if (x % y != 0) return false;
    x /= y;
    for (int i = 1; i <= pn; i++) {
        if (pm[i] >= x) break;
        if (x % pm[i] == 0) return false;
    }
    return true;
}

int main() {
    gp();
    memset(head, -1, sizeof(head));
    n = read();
    for (int i = 1; i <= n; i++) a[i] = read();
    for (int i = 1; i <= n; i++) b[i] = read();
    for (int i = 1; i <= n; i++) c[i] = read();
    for (int i = 1; i <= n; i++) {
        int temp = a[i], cnn = 0;
        for (int j = 1; j <= pn; j++) {
            while (temp % pm[j] == 0) {
                temp /= pm[j];
                cnn++;
            }
            if (temp == 1) break;
        }  
        if (cnn & 1) si[++sn] = i;
        else di[++dn] = i;
    }
    for (int i = 1; i <= sn; i++) {
        for (int j = 1; j <= dn; j++) {
            if (check(a[si[i]], a[di[j]])) {
                add(si[i], di[j], inf, c[si[i]] * c[di[j]]);
            }
        }
    }
    int s = n + 1, t = n + 2;
    for (int i = 1; i <= sn; i++) add(s, si[i], b[si[i]], 0);
    for (int i = 1; i <= dn; i++) add(di[i], t, b[di[i]], 0);
    mcf(s, t);
    printf("%d\n", ans);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Mrzdtz220/p/10929225.html