cogs 2221. [SDOI2016 Round1] 数字配对

                  ★★ 输入文件:pair.in 输出文件:pair.out 简单对比
                    时间限制:1 s 内存限制:128 MB

【题目描述】

  有 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。

【输出格式】

  一行一个数,最多进行多少次配对。

【样例输入】

3

2 4 8

2 200 7

-1 -2 1

【样例输出】

4

【提示】

测试点 1 ~ 3:n≤10,ai≤109,bi=1,∣ci∣≤105;
测试点 4 ~ 5:n≤200,ai≤109,bi≤105,ci=0;
测试点 6 ~ 10:n≤200,ai≤109,bi≤105,∣ci∣≤105。

 题解:

  首先看到让你求匹配,想到网络流中的二分图匹配,然而一个数字只能进行一次匹配,想了很长时间都不知道如何限流,如果直接判断能否匹配是无法确定流量的,正确做法如下:

  X1/X2结果是质数,说明讲两个数分解质因数之后,X1的质因子比X2的质因子多1,其余质因子一样。所以X1,X2的质因子的个数的奇偶性不同。由此可以看到,将N个数分解质因数之后,因子数相同的两个数一定不会匹配,所以把数字按照质因子个数分成两个集合,就形成了二分图中的X集和Y集。

  二分答案,用最大费用最大流来判断,如果流量等于二分的数值且最大费用大于等于0,则成立。

  还有,这题数据范围较坑,inf=1e9还不够。。。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<vector>
  9 using namespace std;
 10 typedef long long LL;
 11 const LL inf=1e15;
 12 LL a[300],b[300],c[300],d[300],N,MAX;
 13 LL prime[1000010],tot;
 14 bool p[300][300];
 15 vector<LL> X,Y;
 16 struct Edge{
 17     LL to,rest,next,cost;
 18 }e[500000];
 19 LL head[300],cnt=1;
 20 
 21 inline void addedge(LL x,LL y,LL r,LL z){
 22     e[++cnt].to=y; e[cnt].rest=r; e[cnt].cost= z; e[cnt].next=head[x]; head[x]=cnt;
 23     e[++cnt].to=x; e[cnt].rest=0; e[cnt].cost=-z; e[cnt].next=head[y]; head[y]=cnt;
 24 }
 25 
 26 LL S,T,maxflow,mincost,dis[300],pre[300];
 27 bool vis[300];
 28 
 29 inline bool SPFA(){
 30     static queue<LL> Q;
 31     while(!Q.empty()) Q.pop();
 32     for(LL i=0;i<=T;i++) dis[i]=-inf,vis[i]=false;
 33     Q.push(S); dis[S]=0; vis[S]=true;
 34     while(!Q.empty()){
 35         LL x=Q.front(); Q.pop(); vis[x]=false;
 36         for(LL i=head[x];i;i=e[i].next){
 37             LL y=e[i].to;
 38             if(e[i].rest>0&&(dis[y]<dis[x]+e[i].cost||dis[y]==-inf)){
 39                 dis[y]=dis[x]+e[i].cost;
 40                 pre[y]=i;
 41                 if(vis[y]==false){
 42                     vis[y]=true;
 43                     Q.push(y);
 44                 }
 45             }
 46         }
 47     }
 48     if(dis[T]>-inf) return true;
 49     return false;
 50 }
 51 inline void update(){
 52     LL flow=inf;
 53     for(LL i=pre[T];i;i=pre[e[i^1].to])
 54         flow=min(flow,e[i].rest);
 55     for(LL i=pre[T];i;i=pre[e[i^1].to]){
 56         e[i].rest-=flow;
 57         e[i^1].rest+=flow;
 58         mincost+=flow*e[i].cost;
 59     }
 60     maxflow+=flow;
 61 }
 62 inline void ASK(){
 63     maxflow=0; mincost=0;
 64     while(SPFA()) 
 65         update();
 66 }
 67 inline bool jud(LL x){
 68     S=0; T=N+2;
 69     for(LL i=0;i<=cnt+10;i++){
 70         e[i].cost=e[i].next=e[i].rest=e[i].to=0;
 71     }
 72     for(LL i=0;i<=N+20;i++) head[i]=0,pre[i]=0;
 73     cnt=1;
 74     for(LL i=0;i<X.size();i++){
 75         addedge(S,X[i],b[X[i]],0);
 76     }
 77     for(LL i=0;i<X.size();i++){
 78         for(LL j=0;j<Y.size();j++){
 79             if(p[X[i]][Y[j]]==true){
 80                 addedge(X[i],Y[j],inf,c[X[i]]*c[Y[j]]);
 81             }
 82         }
 83     }
 84     for(LL i=0;i<Y.size();i++){
 85         addedge(Y[i],N+1,b[Y[i]],0);
 86     }
 87     addedge(N+1,T,x,0);
 88     ASK();
 89     if(mincost>=0&&maxflow==x) return true;
 90     return false;
 91 }
 92 inline LL find(LL l,LL r){
 93     if(l+1>=r){
 94         if(jud(r)==true) return r;
 95         else return l;
 96     }
 97     LL mid=(l+r)>>1;
 98     if(jud(mid)==true) return find(mid,r);
 99     else return find(l,mid-1);
100 }
101 inline void shai(){
102     for(LL i=1;i<=N;i++){
103         for(LL j=1;j<=N;j++){
104             if((a[i]>a[j])&&(a[i]%a[j]==0)){
105                 LL tmp=a[i]/a[j]; bool hhh=true;
106                 for(LL k=2;k*k<=tmp&&k<=tmp;k++){
107                     if(tmp%k==0){
108                         hhh=false; break;    
109                     } 
110                 }
111                 if(hhh==true){
112                     p[i][j]=p[j][i]=true;
113                 //    cout<<i<<" "<<j<<endl;
114                 }
115             }
116         }
117     }
118 }
119 inline void calc(LL x){
120     LL tmp=a[x];
121     for(LL i=2;i*i<=tmp&&i<=tmp;i++){
122         while(tmp%i==0){
123             tmp/=i;
124             d[x]++;
125         }
126     }
127     if(tmp!=1) d[x]++;
128 }
129 int main(){
130     scanf("%lld",&N);
131     for(LL i=1;i<=N;i++) scanf("%lld",&a[i]);
132     for(LL i=1;i<=N;i++) scanf("%lld",&b[i]),MAX+=b[i];
133     for(LL i=1;i<=N;i++) scanf("%lld",&c[i]);
134     shai();
135     for(LL i=1;i<=N;i++) calc(i);
136     for(LL i=1;i<=N;i++){
137         if(d[i]%2==1) X.push_back(i);
138         else Y.push_back(i);
139     }
140     printf("%lld",find(0,inf));
141     return 0;
142 }
原文地址:https://www.cnblogs.com/CXCXCXC/p/5383642.html