zoukankan      html  css  js  c++  java
  • 【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 #include <cstdio>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <queue>
      8 using namespace std;
      9 
     10 #define ll long long
     11 const ll inf=1e18;
     12 const int N=1e5+5;
     13 struct edge{
     14     int from,next,to;
     15     ll v,c;
     16 }e[N];
     17 int first[N],pr[N],prime[N],inq[N],lst[N];
     18 ll A[N],B[N],C[N],dis[N],minf[N];
     19 int S=1,T=2,ade=1,P,n;
     20 queue <int> Q;
     21 
     22 void addedge(int x,int y,ll v,ll c){
     23     e[++ade].to=y;
     24     e[ade].from=x;
     25     e[ade].next=first[x];
     26     e[ade].v=v;
     27     e[ade].c=c;
     28     first[x]=ade;
     29 }
     30 
     31 void ADE(int x,int y,ll v,ll c){
     32     addedge(x,y,v,c);
     33     addedge(y,x,-v,0);
     34 }
     35 
     36 void Prime(){
     37     for (int i=2;i<40000;i++) prime[i]=1;
     38     for (int i=2;i<40000;i++){
     39         if (prime[i]){
     40             pr[++pr[0]]=i;
     41             for (int j=i+i;j<40000;j+=i) prime[j]=0;
     42         }
     43     }
     44 }
     45 
     46 bool check(ll x){
     47     if (x==1) return 0;
     48     for (int i=1;i<=pr[0] && pr[i]<x ;i++) if (!(x%pr[i])) return 0;
     49     return 1;
     50 }
     51 
     52 #define s e[x].to
     53 #define v e[x].v
     54 #define cap e[x].c
     55 #define Cap e[x^1].c
     56 bool SPFA(ll &mf,ll &mc){
     57     for (int i=1;i<=n*2+2;i++) dis[i]=-inf,minf[i]=inf;
     58     Q.push(S),inq[S]=1,dis[S]=0;
     59     while (!Q.empty()){
     60         int p=Q.front();
     61         Q.pop(),inq[p]=0;
     62         for (int x=first[p];x;x=e[x].next){
     63             if (dis[s]<dis[p]+v && cap>0){
     64                 dis[s]=dis[p]+v;
     65                 lst[s]=x;
     66                 minf[s]=min(minf[p],cap);
     67                 if (!inq[s]) Q.push(s),inq[s]=1;
     68             } 
     69         }
     70     }
     71     if (dis[T]==-inf) return 0;
     72     for (int x=lst[T];x;x=lst[e[x].from]) {cap-=minf[T],Cap+=minf[T];}
     73     mf+=minf[T];
     74     mc+=dis[T]*minf[T];
     75     if (mc<0){
     76         mf-=mc/dis[T]+(mc%dis[T]!=0);
     77         return 0;
     78     }
     79     return 1;
     80 }
     81 
     82 void mcmf(){
     83     ll mf=0,mc=0;
     84     while (SPFA(mf,mc));
     85     printf("%lld
    ",mf/2);
     86 }
     87 #undef s
     88 #undef v
     89 #undef c
     90 #undef C
     91 
     92 
     93 int main(){
     94     Prime();
     95     scanf("%d",&n);
     96     for (int i=1;i<=n;i++) scanf("%lld",&A[i]);
     97     for (int i=1;i<=n;i++) scanf("%lld",&B[i]);
     98     for (int i=1;i<=n;i++) scanf("%lld",&C[i]);
     99     for (int i=1;i<=n;i++){
    100         ADE(S,i+2,0,B[i]);
    101         ADE(i+n+2,T,0,B[i]);        
    102         for (int j=1;j<=n;j++){
    103             if (A[i]>A[j] && A[i]%A[j]==0){
    104                 if (check(A[i]/A[j])){
    105                     ADE(i+2,j+n+2,C[i]*C[j],inf);
    106                     ADE(j+2,i+n+2,C[i]*C[j],inf);                    
    107                 }
    108             }
    109         }
    110     }
    111     mcmf();
    112     return 0;
    113 }
    View Code
  • 相关阅读:
    elk中fliebeat的配置文件
    elk 中kafka启动脚本和配置文件
    启动多个logstash脚本
    当使用makemigrations时报错No changes detected
    MySQL5.7.23解压版安装教程
    linux shell变量的截取
    删除mysql数据库中表分区数据
    powershell 定时删除脚本
    利用WinRAR命令行压缩文件或文件夹
    Date对象和正则对象
  • 原文地址:https://www.cnblogs.com/karl07/p/6746425.html
Copyright © 2011-2022 走看看