• BZOJ4514:[SDOI2016]数字配对——题解


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

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

    参考洛谷题解。

    这题很明显是要网络流的,且将关系图建出来之后很明显是二分图。

    那么我们自然的将点归为两类,一类连S,一类连T,这样我们的边就有了方向性,然后就可以跑最大费用最大流了!

    但是难受的是,我们跑的费用要求始终不低于0,这就很难办,我们简单的费用流无法胜任这个工作。

    但是可以发现的是,我们spfa找可行流的时候,显然是先走大费用路径再走小费用路径,于是我们在spfa上直接跑网络流,一边更新dis,一边记录当前节点流入了多少,显然每次只能跑出来一条路径一个流因此会比原版费用流慢很多,复杂度O(玄学)反正能过。

    以及我们当然不必要将二分图建出来dfs,我们记录tot[i]表示第i个数的质因子个数,则奇数为一堆偶数为一堆即可。

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int INF=1e9;
    const ll LINF=1e18;
    const int N=210;
    const int M=N*N*4;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        int to,nxt,w;
        ll b;
    }e[M];
    int n,head[N],cnt,a[N],b[N],c[N],tot[N],limit[N],pre[N];
    ll dis[N];
    bool vis[N];
    inline void add(int u,int v,int w,ll b){
        e[++cnt].to=v;e[cnt].w=w;e[cnt].b=b;e[cnt].nxt=head[u];head[u]=cnt;
        e[++cnt].to=u;e[cnt].w=0;e[cnt].b=-b;e[cnt].nxt=head[v];head[v]=cnt;
    }
    int suan(int k){
        int ans=0;
        for(int i=2;i*i<=k;i++){
        while(k%i==0){
            ans++;k/=i;
        }
        }
        if(k!=1)ans++;
        return ans;
    }
    inline bool spfa(int s,int t,int m){
        queue<int>q;
        memset(vis,0,sizeof(vis));
        memset(pre,-1,sizeof(pre));
        for(int i=1;i<=m;i++)dis[i]=-LINF;
        limit[s]=INF;dis[s]=0;q.push(s);vis[s]=1;
        while(!q.empty()){
        int u=q.front();q.pop();vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].nxt){
            int v=e[i].to;ll b=e[i].b;
            if(e[i].w&&dis[v]<dis[u]+b){
            dis[v]=dis[u]+b;
            limit[v]=min(limit[u],e[i].w);
            pre[v]=i;
            if(!vis[v])
                vis[v]=1,q.push(v);
            }
        }
        }
        return dis[t]>-LINF;
    }
    inline int costflow(int S,int T,int m){
        int flow=0,delta;ll ans=0;
        while(spfa(S,T,m)){
        if(ans+dis[T]<0)break;
        if(dis[T]>=0)delta=limit[T];
        else delta=min((ll)limit[T],ans/(-dis[T]));
        ans+=dis[T]*delta;flow+=delta;
        for(int u=T;pre[u]!=-1;u=e[pre[u]^1].to){
            e[pre[u]].w-=delta;e[pre[u]^1].w+=delta;
        }
        }
        return flow;
    }
    int main(){
        memset(head,-1,sizeof(head));cnt=-1;
        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++)tot[i]=suan(a[i]);
        int S=n+1,T=S+1;
        for(int i=1;i<=n;i++){
        if(tot[i]&1)add(S,i,b[i],0);
        else add(i,T,b[i],0);
        if(tot[i]&1){
            for(int j=1;j<=n;j++){
            if((a[j]%a[i]==0&&tot[i]+1==tot[j])||
               (a[i]%a[j]==0&&tot[j]+1==tot[i]))
                add(i,j,INF,(ll)c[i]*c[j]);
            }
        }
        }
        printf("%d
    ",costflow(S,T,T));
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    bzoj千题计划239:bzoj4069: [Apio2015]巴厘岛的雕塑
    bzoj千题计划238:bzoj3668: [Noi2014]起床困难综合症
    hdu 3022 Sum of Digits
    在RAC中,当私有网线拔了后,会怎么样?
    CVU介绍
    oracle rac 日志体系结构!
    oracle 内存结构 share pool sql解析的过程
    Oracle逻辑读详解
    共享池之八:软解析、硬解析、软软解析 详解一条SQL在library cache中解析涉及的锁
    共享池之六:shared pool latch/ library cache latch /lock pin 简介
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9179590.html
Copyright © 2020-2023  润新知