zoukankan      html  css  js  c++  java
  • [bzoj4514] [Sdoi2016]数字配对

      费用流。。

      先把a数组里的数全部质因数分解,判断ai/aj是否为质数,就看质因数互相抵消后是不是只剩一个质因数。

      满足条件的数就连边

      接下来我想拆点建二分图。。然而由题解可得,连边的两个数 的质因数个数 的奇偶性肯定不同。。

      就相当于自带黑白染色...所以奇数个连汇,偶数个连源就行了= =

      因为有价值总和不小于0的限制。所以找到一条价值为负的增广路后,不一定能流满。

      但是因为求费用流的原始对偶算法自带限制流量的功能。。所以其实改一个数就能照常多路增广了= =

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #define ll long long
      5 using namespace std;
      6 const int maxn=205,inf1=1002333333;
      7 ll inf;
      8 struct zs{
      9     int too,pre,flow;
     10     ll cost;
     11 }e[1002333];int tot,last[maxn];
     12 int mp[maxn][23],mp1[maxn][23],psum[maxn],num[maxn];
     13 int a[maxn],b[maxn],c[maxn];
     14 int p[32333],pnum;
     15 int dl[100233];
     16 ll dis[maxn],sm;
     17 int i,j,k,n,m,ans,s,t;
     18 bool isp[32333],u[maxn],ins[maxn];
     19 
     20 
     21 int ra,fh;char rx;
     22 inline int read(){
     23     rx=getchar(),ra=0,fh=1;
     24     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
     25     if(rx=='-')fh=-1,rx=getchar();
     26     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
     27 }
     28 inline void insert(int a,int b,int c,ll d){
     29 //    printf("   %d-->%d  %d %lld
    ",a,b,c,d);
     30     e[++tot].too=b,e[tot].flow=c,e[tot].cost=d ,e[tot].pre=last[a],last[a]=tot;
     31     e[++tot].too=a,e[tot].flow=0,e[tot].cost=-d,e[tot].pre=last[b],last[b]=tot;
     32 }
     33 inline void prerun_p(){
     34     int mx=32333;register int i,j;
     35     memset(isp,1,mx);
     36     isp[1]=0;
     37     for(i=2;i<mx;i++)if(isp[i])
     38         for(j=i<<1,p[++pnum]=i;j<mx;j+=i)isp[j]=0;
     39 }
     40 inline void prerun_div(){
     41     int tmp;register int j;
     42     for(int i=1;i<=n;i++){
     43         tmp=a[i];
     44         for(j=1;j<=pnum&&p[j]*p[j]<=tmp;j++)
     45             if(tmp%p[j]==0){
     46                 mp[i][++num[i]]=p[j];
     47                 while(tmp%p[j]==0)
     48                     ++mp1[i][num[i]],tmp/=p[j],psum[i]++;
     49             }
     50         if(tmp>1)mp[i][++num[i]]=tmp,mp1[i][num[i]]=1,psum[i]++;
     51     }
     52 }
     53 inline bool check(int i,int j){
     54     if(a[j]%a[i]!=0||psum[j]>psum[i]+1)return 0;
     55     if(a[i]==1)return psum[j]==1;
     56     register int k;int x=0;bool f;
     57     if(psum[j]>psum[i]){
     58         for(k=1,f=0;k<=num[j]&&x<2;k++)
     59             if(mp[j][k]!=mp[i][k-f])f=1,x+=mp1[j][k];else x+=mp1[j][k]-mp1[i][k-f];
     60         return x==1;
     61     }else{
     62         for(k=1;k<=num[j]&&x<2;k++)
     63             x+=mp1[j][k]-mp1[i][k];
     64         return x==1;
     65     }
     66 }
     67 inline void build(){
     68     int i,j,i1,j1;
     69     for(i=1;i<=n;i++)if(psum[i]&1)insert(i,t,b[i],0);else insert(s,i,b[i],0);
     70     for(i=1;i<=n;i++)for(j=1;j<=n;j++)
     71         if(a[i]<a[j]&&((psum[i]^psum[j])&1))
     72             if(check(i,j)){
     73                 if(psum[i]&1)i1=j,j1=i;else i1=i,j1=j;
     74                 insert(i1,j1,inf1,(ll)c[i]*c[j]);//printf("  checked:  %d %d
    ",a[i],a[j]);
     75             }
     76 }
     77 
     78 
     79 inline bool spfa(){
     80     memset(dis,180,(t+1)<<3);
     81     int l=0,r=1,i,now;dl[1]=s,u[s]=1,dis[s]=0;
     82     while(l<r)
     83         for(now=dl[++l],u[now]=0,i=last[now];i;i=e[i].pre)
     84             if(e[i].flow&&dis[e[i].too]<dis[now]+e[i].cost){
     85                 dis[e[i].too]=dis[now]+e[i].cost;
     86                 if(!u[e[i].too])dl[++r]=e[i].too,u[e[i].too]=1;
     87             }
     88     return dis[t]>-inf;
     89 }
     90 inline int dfs(int x,int mx){
     91     if(x==t)return mx;
     92     int i,used=0,w;ins[x]=1;
     93     for(i=last[x];i;i=e[i].pre)if(e[i].flow&&dis[e[i].too]==dis[x]+e[i].cost&&!ins[e[i].too])
     94         if((w=dfs(e[i].too,min(mx-used,e[i].flow)))){
     95             used+=w,e[i].flow-=w,e[i^1].flow+=w;
     96             if(used==mx){ins[x]=0;return mx;}
     97         }
     98     ins[x]=0,dis[x]=-inf;return used;
     99 }
    100 int main(){
    101     inf=inf1;inf*=inf;
    102     n=read();
    103     for(i=1;i<=n;i++)a[i]=read();
    104     for(i=1;i<=n;i++)b[i]=read();
    105     for(i=1;i<=n;i++)c[i]=read();
    106     prerun_p();prerun_div();
    107     s=0,t=n+1,tot=1;
    108     build();
    109     int w;
    110     while(spfa())
    111         if(dis[t]>=0)w=dfs(s,inf1),sm+=dis[t]*w,ans+=w;
    112         else{
    113             if(sm+dis[t]<0)break;
    114             w=dfs(s,sm/(-dis[t])),sm+=dis[t]*w,ans+=w;
    115         }
    116     printf("%d
    ",ans);
    117     return 0;
    118 }
    View Code

     然而这题主要耗时完全不在费用流上QAQ

  • 相关阅读:
    396 Rotate Function 旋转函数
    395 Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子串
    394 Decode String 字符串解码
    393 UTF-8 Validation UTF-8 编码验证
    392 Is Subsequence 判断子序列
    391 Perfect Rectangle 完美矩形
    390 Elimination Game 淘汰游戏
    389 Find the Difference 找不同
    388 Longest Absolute File Path 最长的绝对文件路径
    387 First Unique Character in a String 字符串中的第一个唯一字符
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5444827.html
Copyright © 2011-2022 走看看