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;
        
    }
  • 相关阅读:
    iphone5刷机教程
    ios开发之--/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: bad interpreter: No such file
    浅谈iPhone OS(iOS)架构
    ios开发之--使用xib适配iPhone X
    ios开发之--armv7,armv7s,arm64,i386,x86_64详解
    ios开发之--UIButton中imageView和titleLabel的位置调整
    gem install cocoapods ERROR: While executing gem ... (Gem::FilePermissionError)
    ios开发之NSString用strong还是用copy?
    ios开发之--高德地图以及自定义大头针和气泡、导航
    iOS
  • 原文地址:https://www.cnblogs.com/evenbao/p/10360017.html
Copyright © 2011-2022 走看看