zoukankan      html  css  js  c++  java
  • 【BZOJ 4514】[Sdoi2016]数字配对 费用流

    利用spfa流的性质,我直接拆两半,正解分奇偶(妙),而且判断是否整除且质数我用的是暴力根号,整洁判断质数个数差一(其他非spfa流怎么做?)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    typedef long long LL;
    const int N=205;
    const int P=N;
    const int E=N*N/2;
    const int Inf=0x3f3f3f3f;
    const LL oo=0xafafafafafafafafLL;
    struct V{
      int to,next,f;
      LL c;
    }c[E];
    int head[P],t=1;
    inline void add(int x,int y,int z,LL _){
      c[++t].to=y,c[t].next=head[x],head[x]=t,c[t].f=z,c[t].c=_;
    }
    int n;
    int key[N],cnt[N],val[N];
    int S,T;
    LL dis[P];
    int anc[P];
    int q[P],front,back;
    bool in[P];
    int size[N];
    LL ans,sum;
    inline bool spfa(){
      memset(dis,0xaf,sizeof(dis));
      dis[S]=0,in[S]=true,q[back++]=S;
      if(back==P)back=0;
      while(front!=back){
        int x=q[front++];in[x]=false;
        if(front==P)front=0;
        for(int i=head[x];i;i=c[i].next)
          if(c[i].f&&dis[x]+c[i].c>dis[c[i].to]){
            dis[c[i].to]=dis[x]+c[i].c,anc[c[i].to]=i;
            if(!in[c[i].to]){
              q[back++]=c[i].to,in[c[i].to]=true;
              if(back==P)back=0;
            }
          }
      }
      return dis[T]!=oo;
    }
    inline int shoot(){
      int f=Inf;
      for(int i=anc[T];i;i=anc[c[i^1].to])f=std::min(f,c[i].f);
      for(int i=anc[T];i;i=anc[c[i^1].to])c[i].f-=f,c[i^1].f+=f;
      return f;
    }
    int main(){
      scanf("%d",&n);
      S=n+1,T=S+1;
      for(int i=1;i<=n;++i){
        scanf("%d",&key[i]);
        int x=key[i];
        for(int j=2;j*j<=x;++j)
          while(x%j==0)++size[i],x/=j;
        if(x!=1)++size[i];
      }
      for(int i=1;i<=n;++i){
        scanf("%d",&cnt[i]);
        if(size[i]&1){
          add(S,i,cnt[i],0);
          add(i,S,0,0);
        }else{
          add(i,T,cnt[i],0);
          add(T,i,0,0);
        }
      }
      for(int i=1;i<=n;++i)scanf("%d",&val[i]);
      for(int i=1;i<=n;++i)
        if(size[i]&1)
          for(int j=1;j<=n;++j)
            if((size[j]&1)==0){
              int x=key[i],y=key[j];
              if(x>y)std::swap(x,y);
              if(y%x==0&&std::abs(size[i]-size[j])==1){
                add(i,j,Inf,(LL)val[i]*val[j]);
                add(j,i,0,-(LL)val[i]*val[j]);
              }
            }
      while(spfa()){
        int f=shoot();
        if(f*dis[T]+ans<0){
          for(int i=1;i<=f&&ans+dis[T]>=0;++i)
            ans+=dis[T],++sum;
          break;
        }
        ans+=f*dis[T];
        sum+=f;
      }
      printf("%lld",sum);
      return 0;
    }
  • 相关阅读:
    VMwarePro密钥
    Windows事件ID
    python中安装下载超时,下载不了安装包
    PNG文件结构分析 ---Png解析
    世界协调时间(UTC)与中国标准时间
    计算机用户权限比较
    pikachu-xx型注入
    pikachu-搜索型注入 #手工注入
    显示桌面图标
    SQL2005 数据库还原到 SQL2008 错误 3145 解决办法
  • 原文地址:https://www.cnblogs.com/TSHugh/p/8016336.html
Copyright © 2011-2022 走看看