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;
    }
  • 相关阅读:
    ArrayList removeRange方法分析
    LinkedHashMap源码分析(基于JDK1.6)
    LinkedList原码分析(基于JDK1.6)
    TreeMap源码分析——深入分析(基于JDK1.6)
    51NOD 2072 装箱问题 背包问题 01 背包 DP 动态规划
    51 NOD 1049 最大子段和 动态规划 模板 板子 DP
    51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子
    8月20日 训练日记
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/TSHugh/p/8016336.html
Copyright © 2011-2022 走看看