zoukankan      html  css  js  c++  java
  • [SDOI 2016] 数字配对

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=4514

    [算法]

             记Cnti表示第i个数的质因子次数之和

             那么i与j可以配对当且仅当 : Cnti = Cntj + 1且ai为aj的倍数或Cntj = Cnti + 1且aj为ai的倍数

             那么Cnti为奇数与Cnti为偶数的点构成了两个集合

             考虑费用流 :

             将源点与Cnti为奇数的点连一条容量为bi , 费用为0的边

             将Cnti为偶数的点向汇点连一条容量为bi , 费用为0的边

             对于所有可以配对的(i , j) , 将i与j连一条容量为正无穷 , 费用为CiCj的边

             答案即为这张图的最大费用最大流

             但注意由于题目中要求费用为非负数 , 所以可以考虑贪心 :

             由于最大费用最大流每次找到的增广路的费用单调递减 , 所以优先考虑费用大的

             时间复杂度 : O(Costflow(N , N ^ 2))

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    #define N 520
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const ll inf = 1e18;
    
    struct edge
    {
            int to;
            ll w , cost;
            int nxt;
    } e[N * N * 4];
    
    int n , tot , S , T;
    ll sum , ans;
    int a[N] , b[N] , c[N] , cnt[N] , pre[N] , head[N];
    ll dist[N] , incf[N];
    bool inq[N];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u , int v , ll w , ll cost)
    {
            ++tot;
            e[tot] = (edge){v , w , cost , head[u]};
            head[u] = tot;
            ++tot;
            e[tot] = (edge){u , 0 , -cost , head[v]};
            head[v] = tot;
    }
    inline int get(int x)
    {
            int ret = 0;
            for (int i = 2; i <= sqrt(x); i++)
            {
                    while (x % i == 0)
                    {
                            x /= i;
                            ++ret;
                    }
            }
            if (x > 1) ++ret;
            return ret;
    }
    inline bool spfa()
    {
            queue< int > q;
            for (int i = 1; i <= T; i++)
            {
                    inq[i] = false;
                    dist[i] = -inf;
                    incf[i] = inf;
            }
            pre[S] = 0;
            inq[S] = true;
            dist[S] = 0;
            incf[S] = inf;
            q.push(S);        
            while (!q.empty())
            {
                    int cur = q.front();
                    q.pop();
                    inq[cur] = false;
                    for (int i = head[cur]; i; i = e[i].nxt)
                    {
                            int v = e[i].to;
                            ll w = e[i].w , cst = e[i].cost;
                            if (w > 0 && dist[cur] + cst > dist[v])
                            {
                                    dist[v] = dist[cur] + cst;
                                    incf[v] = min(incf[cur] , w);
                                    pre[v] = i;
                                    if (!inq[v])
                                    {
                                            inq[v] = true;
                                            q.push(v);
                                    }
                            }
                     }
            }
            if (dist[T] != -inf) return true;
            else return false;
    }
    inline bool update()
    {
            if (sum + dist[T] * incf[T] >= 0)
            {
                    sum += dist[T] * incf[T];
                    ans += incf[T];
                    int now = T;
                    while (pre[now])
                    {
                            e[pre[now]].w -= incf[T];
                            e[pre[now] ^ 1].w += incf[T];
                            now = e[pre[now] ^ 1].to;
                    }
                    return true;
            }    else
            {
                    ans += sum / (-dist[T]);
                    return false;
            }
    }
    
    int main()
    {
            
            read(n);
            tot = 1;
            for (int i = 1; i <= n; i++) read(a[i]);
            for (int i = 1; i <= n; i++) read(b[i]);
            for (int i = 1; i <= n; i++) read(c[i]);
            for (int i = 1; i <= n; i++) cnt[i] = get(a[i]);
            S = n + 1 , T = S + 1;
            for (int i = 1; i <= n; i++)
                    if (cnt[i] & 1) addedge(S , i , b[i] , 0);
                    else addedge(i , T , b[i] , 0);
            for (int i = 1; i <= n; i++)
            {
                    if (cnt[i] & 1)
                    {
                            for (int j = 1; j <= n; j++)
                            {
                                    if (((a[j] % a[i] == 0) && (cnt[j] == cnt[i] + 1)) || ((a[i] % a[j] == 0) && (cnt[i] == cnt[j] + 1)))
                                            addedge(i , j , inf , 1ll * c[i] * c[j]);        
                            }        
                    }        
            }
            while (spfa() && update());
            printf("%lld
    " , ans);
            
            return 0;
        
    }
  • 相关阅读:
    poj 3666 Making the Grade
    poj 3186 Treats for the Cows (区间dp)
    hdu 1074 Doing Homework(状压)
    CodeForces 489C Given Length and Sum of Digits...
    CodeForces 163A Substring and Subsequence
    CodeForces 366C Dima and Salad
    CodeForces 180C Letter
    CodeForces
    hdu 2859 Phalanx
    socket接收大数据流
  • 原文地址:https://www.cnblogs.com/evenbao/p/10360017.html
Copyright © 2011-2022 走看看