BZOJ 4514[Sdoi2016]数字配对 费用流

Posted TS_Hugh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 

以上是关于BZOJ 4514[Sdoi2016]数字配对 费用流的主要内容,如果未能解决你的问题,请参考以下文章

[Bzoj4514][Sdoi2016]数字配对(费用流)

图论(费用流):BZOJ 4514 [Sdoi2016]数字配对

BZOJ4514: [Sdoi2016]数字配对

BZOJ4514SDOI2016数字配对 [费用流]

bzoj4514: [Sdoi2016]数字配对 图论-费用流

bzoj4514 [Sdoi2016]数字配对(网络流)