[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\n",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\n",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\n",ans);
117     return 0;
118 }

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

时间: 2024-11-10 14:50:27

[bzoj4514] [Sdoi2016]数字配对的相关文章

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

4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2204  Solved: 865[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对.

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

Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在获得的价值总和不小于 0 的前提下,求最多进行多少次配对. Input 第一行一个整数 n. 第二行 n 个整数 a1.a2.--.an. 第三行 n 个整数 b1.b2.--.bn. 第四行 n 个整数 c1.c2.--

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

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2197  Solved: 859[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在获得的价值总和不小于 0 的前提下,求最

BZOJ4514 [Sdoi2016]数字配对 【费用流】

题目 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在获得的价值总和不小于 0 的前提下,求最多进行多少次配对. 输入格式 第一行一个整数 n. 第二行 n 个整数 a1.a2.--.an. 第三行 n 个整数 b1.b2.--.bn. 第四行 n 个整数 c1.c2.--.cn. 输出格式

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

[bzoj4514]: [Sdoi2016]数字配对 好像正常的做法是建二分图? 我的是拆点然后 S->i cap=b[i] cost=0 i'->T cap=b[i] cost=0 然后能匹配的两点i,j 连 i->j' cap=inf cost=c[i]*c[j] 跑最大费用流,直到 cost<0 或 全部增广完 最后flow/2就是答案 1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #i

【BZOJ4514】[Sdoi2016]数字配对 费用流

[BZOJ4514][Sdoi2016]数字配对 Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在获得的价值总和不小于 0 的前提下,求最多进行多少次配对. Input 第一行一个整数 n. 第二行 n 个整数 a1.a2.…….an. 第三行 n 个整数 b1.b2.

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

4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 820  Solved: 345[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在

4514: [Sdoi2016]数字配对

4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1305  Solved: 498[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对.

【BZOJ-4514】数字配对 最大费用最大流 + 质因数分解 + 二分图 + 贪心 + 线性筛

4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 726  Solved: 309[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在