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


    数字配对

    Time Limit: 10 Sec  Memory Limit: 128 MB
    [Submit][Status][Discuss]

    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、……、cn。

    Output

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

    Sample Input

      3
      2 4 8
      2 200 7
      -1 -2 1

    Sample Output

      4

    HINT

       n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5

    Solution

      显然是一个费用流,并且这可以是一个二分图,由于 ai/aj 要是质数,那显然可以根据质因子个数的奇偶分类。

      然后跑一跑最大费用最大流。判断一下值要>=0即可统计入答案。mmpBearChild查了一个下午错,发现是INF开小了qaq。

    Code

      1 #include<iostream>    
      2 #include<string>    
      3 #include<algorithm>    
      4 #include<cstdio>    
      5 #include<cstring>    
      6 #include<cstdlib>
      7 #include<cmath>
      8 #include<map>
      9 using namespace std;  
     10 typedef long long s64;
     11   
     12 const int ONE = 205*205;
     13 const int INF = 2147483640;
     14  
     15 int n;
     16 int a[ONE], b[ONE], c[ONE];
     17 s64 dist[ONE];
     18 int vis[ONE], q[ONE*10], pre[ONE];
     19 int first[ONE], go[ONE], next[ONE], pas[ONE], from[ONE], tot;
     20 int pNum[ONE];
     21 int odd[ONE],Onum, eve[ONE],Enum;
     22 int S, T, Ans;
     23 int prime[ONE], isp[ONE], p;
     24 s64 Val, w[ONE];
     25   
     26 int get()
     27 {    
     28         int res=1,Q=1;char c;    
     29         while( (c=getchar())<48 || c>57 ) 
     30         if(c=='-')Q=-1; 
     31         res=c-48;     
     32         while( (c=getchar())>=48 && c<=57 )    
     33         res=res*10+c-48;    
     34         return res*Q;
     35 }
     36 
     37 void Getp(int MaxN)
     38 {
     39         for(int i=2; i <= MaxN; i++)
     40         {
     41             if(!isp[i]) prime[++p] = i;
     42             for(int j=1; j <= prime[p], i*prime[j] <= MaxN; j++)
     43             {
     44                 isp[i * prime[j]] = 1;
     45                 if(i % prime[j] == 0) break;
     46             }
     47         }
     48 }
     49   
     50 int Factor(int x)
     51 {
     52         int res = 0;
     53         while(x != 1)
     54         {
     55             for(int i=1; i<=p; i++)
     56             if(x % prime[i] == 0)
     57             {
     58                 x /= prime[i];
     59                 res++;
     60                 break;
     61             }
     62         }
     63         return res;
     64 }
     65   
     66 int PD(int x, int y)
     67 {
     68         if(x > y) swap(x, y);
     69         if(x==0 || y==0 || y%x!=0) return 0;
     70         x = y / x;
     71         for(int i=2; i<x; i++)
     72         if(x % i == 0) return 0;
     73         return 1;
     74 }
     75   
     76 int Add(int u, int v, int flow, s64 z)
     77 {
     78         next[++tot]=first[u];   first[u]=tot;   go[tot]=v;  pas[tot]=flow;  w[tot]=z;   from[tot]=u;
     79         next[++tot]=first[v];   first[v]=tot;   go[tot]=u;  pas[tot]=0;     w[tot]=-z;  from[tot]=v;
     80 }
     81    
     82 bool Bfs()
     83 {
     84         for(int i=S; i<=T; i++) dist[i] = -1e18;
     85         int tou = 0, wei = 1;
     86         q[1] = S;   vis[S] = 1; dist[S] = 0;
     87         while(tou < wei)
     88         {
     89             int u = q[++tou];
     90             for(int e=first[u]; e; e=next[e])
     91             {
     92                 int v=go[e];
     93                 if(dist[v] < dist[u] + w[e] && pas[e])
     94                 {
     95                     dist[v] = dist[u] + w[e];
     96                     pre[v] = e;
     97                     if(!vis[v])
     98                     {
     99                         q[++wei] = v;
    100                         vis[v] = 1;
    101                     }
    102                 }
    103             }
    104             vis[u] = 0;
    105         }
    106         return dist[T] != -1e18;
    107 }
    108   
    109 void Deal()
    110 {
    111         int x = INF;
    112         for(int e=pre[T]; e; e=pre[from[e]]) x = min(x, pas[e]);
    113         if(Val + dist[T] * x >= 0)
    114         {
    115             for(int e=pre[T]; e; e=pre[from[e]])
    116             {
    117                 pas[e] -= x;
    118                 pas[((e-1)^1)+1] += x;
    119             }
    120             Val += dist[T] * x;
    121             Ans += x;
    122             return;
    123         }
    124         printf("%d", Ans - Val / dist[T]);
    125         exit(0);
    126 }
    127   
    128 int main()
    129 {
    130         Getp(ONE);
    131         n = get();
    132         for(int i=1; i<=n; i++) a[i] = get(), pNum[i] = Factor(a[i]);
    133         for(int i=1; i<=n; i++) b[i] = get();
    134         for(int i=1; i<=n; i++) c[i] = get();
    135           
    136         S = 0; T = n+1;
    137         for(int i=1; i<=n; i++)
    138         {
    139             if(pNum[i] & 1) Add(S,i, b[i],0), odd[++Onum] = i;
    140             else Add(i,T, b[i],0), eve[++Enum] = i;
    141         }
    142           
    143         for(int i=1; i<=Onum; i++)
    144         for(int j=1; j<=Enum; j++)
    145         {
    146             int x = odd[i], y = eve[j];
    147             if( PD(a[x], a[y]) )
    148                 Add(x,y, INF,(s64)c[x]*c[y]);
    149         }
    150         
    151         while(Bfs()) Deal();
    152         printf("%d", Ans - Val / dist[T]);
    153 }
    View Code
  • 相关阅读:
    jquery-5 jQuery筛选选择器
    百度富文本编辑器ueditor使用启示
    前端开发思路
    世界硬币:比特币类似的评分系统!
    百度面试题 号码找到符合条件
    彩色图像--色彩空间 YIQ 、YUV 、YCbCr 、YC1C2 和I1I2I3
    HDU 4915 Parenthese sequence
    Visual FoxPro 6.0~9.0解决方案和实例文档和CD写入原件下载
    DWR入门的例子(一个)
    写自己的第二级处理器(3)——Verilog HDL行为语句
  • 原文地址:https://www.cnblogs.com/BearChild/p/6941123.html
Copyright © 2020-2023  润新知