zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    【产品】八问
    【设计总结】QQ主题升级
    新冠疫情下的世界是怎么样的?他给我们带来了一份答案
    vue项目实战:vuex板块的考虑和封装
    vue项目实战:directives filters mixins util 内容的封装
    vue项目实战:api管理和封装
    vue项目实战:路由文件的配置
    vue项目实战:项目入口代码展示公共js文件夹内容
    vue项目实战:项目布局和公共文件夹的确定
    vue项目实战:项目搭建使用vue+Es6+webpack+vuex+axios+Element ui完成 文件夹内容的确定
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5383642.html
Copyright © 2011-2022 走看看