• bzoj4514: [Sdoi2016]数字配对


    很沙茶很沙茶。。调了一个下午。。。结果就是下界大了。。

    做法:可以得到一个num数组,表示这个数的质因数个数,然后若A[i]%A[j]==0并且num[i]==num[j]+1 说明它可以匹配

    这样一来又可以发现按奇偶分是二分图没有环,二分答案,最大费用最大流,判断是否满流且费用大于0即可。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int inf=(1<<30);
    
    int A[11000],B[11000],num[11000];
    LL C[11000];
    int getnum(int k)
    {
        int s=0;
        for(int i=2;i*i<=k;i++)
        {
            if(k%i==0)
                while(k%i==0)k/=i,s++;
        }
        if(k>1)s++;
        return s;
    }
    
    //-----------------------------------------
    
    int n,st,ed,S;
    struct node
    {
        int x,y,c,next,other;LL d;
    }a[210000],e[210000];int len,last[11000],elen,elast[11000];
    void eins(int x,int y,int c,LL d)
    {
        int k1,k2;
        
        elen++;k1=elen;
        e[elen].x=x;e[elen].y=y;e[elen].c=c;e[elen].d=d;
        e[elen].next=elast[x];elast[x]=elen;
        
        elen++;k2=elen;
        e[elen].x=y;e[elen].y=x;e[elen].c=0;e[elen].d=-d;
        e[elen].next=elast[y];elast[y]=elen;
        
        e[k1].other=k2;
        e[k2].other=k1;
    }
    void composition()
    {
        elen=0;memset(elast,0,sizeof(elast));
        st=n+1;ed=n+2;S=n+3;
        
        for(int i=1;i<=n;i++)
            if(num[i]%2==1)eins(st,i,B[i],0);
            else eins(i,ed,B[i],0);
        
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if((num[i]+1==num[j]&&A[j]%A[i]==0)||(num[i]==num[j]+1&&A[i]%A[j]==0))
                    if(num[i]%2==1)eins(i,j,inf,C[i]*C[j]);
                    else eins(j,i,inf,C[i]*C[j]);
    }
    //~~~~~~~~~~~~~~
    
    void ins(int x,int y,int c,LL d)
    {
        int k1,k2;
        
        len++;k1=len;
        a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d;
        a[len].next=last[x];last[x]=len;
        
        len++;k2=len;
        a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d;
        a[len].next=last[y];last[y]=len;
        
        a[k1].other=k2;
        a[k2].other=k1;
    }
    
    //-----------------------------------------
    
    int cc;LL cost;
    int list[11000];bool v[11000];
    LL d[11000];
    int c[11000],pre[11000];
    bool spfa()
    {
        for(int i=1;i<=n+4;i++)d[i]=-(LL(inf))*(LL(inf));
        d[S]=0;
        memset(c,0,sizeof(c));c[S]=inf;
        memset(pre,0,sizeof(pre));
        memset(v,false,sizeof(v));v[S]=true;
        int head=1,tail=2;list[head]=S;
        while(head!=tail)
        {
            int x=list[head];
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(d[y]<d[x]+a[k].d&&a[k].c>0)
                {
                    d[y]=d[x]+a[k].d;
                    c[y]=min(c[x],a[k].c);
                    pre[y]=k;
                    if(v[y]==false)
                    {
                        v[y]=true;
                        list[tail]=y;
                        tail++;if(tail==10100)tail=1;
                    }
                }
            }
            v[x]=false;
            head++;if(head==10100)head=1;
        }
        if(d[ed]<=-(LL(inf))*(LL(inf)))return false;
        else
        {
            cc+=c[ed];
            cost+=d[ed]*c[ed];
            int y=ed;
            while(pre[y]!=0)
            {
                int k=pre[y];
                a[k].c-=c[ed];
                a[a[k].other].c+=c[ed];
                y=a[k].x;
            }
            return true;
        }
    }
    bool check(int mid)
    {
        len=elen;
        memcpy(a,e,sizeof(a));
        memcpy(last,elast,sizeof(last));
        ins(S,st,mid,0);
        
        cc=0;cost=0;
        while(spfa()==true);
        if(cc==mid&&cost>=0)return true;
        else return false;
    }
    int main()
    {
        freopen("pair.in","r",stdin);
        freopen("pair.out","w",stdout);
        
        int sum=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&A[i]),num[i]=getnum(A[i]);
        for(int i=1;i<=n;i++)scanf("%d",&B[i]),sum+=B[i];
        for(int i=1;i<=n;i++)scanf("%lld",&C[i]);
        composition();
        
        int l=0,r=sum/2,ans=0;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(check(mid)==true)
            {
                l=mid+1;
                ans=mid;
            }
            else r=mid-1;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    配置Tomcat 输入ip直接访问自己的页面
    为什么hashMap的容量是2的幂次
    LinkedList源码详解
    以太网和Zigbee的家居信息采集系统
    无线LED智能照明控制系统
    ZigBee无线应变采集装置
    ZigBee红外远程监控系统设计
    ZigBee教室照明监控系统设计
    基于物联网的智能医护系统研究
    物联网的低成本乳品质量链追溯平台设计
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8885268.html
Copyright © 2020-2023  润新知