zoukankan      html  css  js  c++  java
  • 【BZOJ 3308】 3308: 九月的咖啡店 (费用流|二分图最大权匹配)

    3308: 九月的咖啡店

    Time Limit: 30 Sec  Memory Limit: 128 MB
    Submit: 244  Solved: 86

    Description

    深绘里在九份开了一家咖啡让,如何调配咖啡民了她每天的头等大事
    我们假设她有N种原料,第i种原料编号为i,调配一杯咖啡则需要在这
    里若干种兑在一起。不过有些原料不能同时在一杯中,如果两个编号
    为i,j的原料,当且仅当i与j互质时,才能兑在同一杯中。
    现在想知道,如果用这N种原料来调同一杯咖啡,使用的原料编号之和
    最大可为多少。

    Input

    一个数字N

    Output

    如题

    Sample Input

    10

    Sample Output

    30

    HINT



    1<=N<=200000

    Source

     

    【分析】

      其实一开始也是认为每个质数自己搞成一个极大的数。

      后来也发现大于$sqrt n$可能是有问题的。

      然后最i多只会有两个数,且一个大于$sqrt n$,一个小于【这种东西还是靠胆量猜吧?或许可以证明?

      可以先每个质数自己搞成一个极大的数,然后建二分图,

        若a,b能配对

        a,b连边 权值VabVaVb

         【费用流ins也能打错的我。。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 #define Maxn 200010
      9 #define Maxm 200010
     10 #define INF 0xfffffff
     11 #define LL long long
     12 
     13 int mymin(int x,int y) {return x<y?x:y;}
     14 
     15 struct node
     16 {
     17     int x,y,f,c,o,next;
     18 }t[Maxm*2];
     19 int first[Maxn],len;
     20 
     21 int st,ed;
     22 void ins(int x,int y,int f,int c)
     23 {
     24     if(c<=0&&x!=st&&y!=ed) return;
     25     t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c;
     26     t[len].next=first[x];first[x]=len;t[len].o=len+1;
     27     t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c;
     28     t[len].next=first[y];first[y]=len;t[len].o=len-1;
     29 }
     30 
     31 queue<int > q;
     32 bool inq[Maxn];
     33 LL dis[Maxn],flow[Maxn];
     34 int pre[Maxn];
     35 bool bfs()
     36 {
     37     memset(inq,0,sizeof(inq));
     38     // memset(dis,63,sizeof(dis));
     39     for(int i=1;i<=ed;i++) dis[i]=-INF;
     40     while(!q.empty()) q.pop();
     41     q.push(st);dis[st]=0;flow[st]=INF;
     42     inq[st]=1;
     43     while(!q.empty())
     44     {
     45         int x=q.front();
     46         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     47         {
     48             int y=t[i].y;
     49             if(dis[y]<dis[x]+t[i].c)
     50             {
     51                 dis[y]=dis[x]+t[i].c;
     52                 flow[y]=mymin(flow[x],t[i].f);
     53                 pre[y]=i;
     54                 if(!inq[y])
     55                 {
     56                     inq[y]=1;
     57                     q.push(y);
     58                 }
     59             }
     60         }
     61         q.pop();inq[x]=0;
     62     }
     63     return dis[ed]>-INF;
     64 }
     65 
     66 LL sum;
     67 void max_flow()
     68 {
     69     while(bfs())
     70     {
     71         if(dis[ed]<0) return;
     72         sum+=flow[ed]*dis[ed];
     73         int x=ed;
     74         while(x!=st)
     75         {
     76             t[pre[x]].f-=flow[ed];
     77             t[t[pre[x]].o].f+=flow[ed];
     78             x=t[pre[x]].x;
     79         }
     80     }
     81 }
     82 
     83 int n;
     84 LL pri[Maxn];int pl;
     85 LL as[Maxn];
     86 bool vis[Maxn];
     87 void init()
     88 {
     89     memset(vis,0,sizeof(vis));
     90     for(int i=2;i<=n;i++)
     91     {
     92         if(!vis[i]) pri[++pl]=i;
     93         for(int j=1;j<=pl;j++)
     94         {
     95             if(i*pri[j]>n) break;
     96             vis[i*pri[j]]=1;
     97             if(i%pri[j]==0) break;
     98         }
     99     }
    100     for(int i=1;i<=pl;i++)
    101     {
    102         as[i]=pri[i];
    103         while(as[i]*pri[i]<=n) as[i]*=pri[i];
    104         sum+=as[i];
    105     }
    106     int i;
    107     for(i=1;pri[i]*pri[i]<n&&i<=pl;i++)
    108      for(int j=pl;pri[j]*pri[j]>=n;j--)
    109      {
    110          int x=pri[i]*pri[j];
    111          if(x>n) continue;
    112          while(x*pri[i]<=n) x*=pri[i];
    113          ins(i,j,1,x-as[i]-as[j]);
    114      }
    115     st=pl+1;ed=st+1;
    116     for(int i=1;pri[i]*pri[i]<n&&i<=pl;i++) 
    117         ins(st,i,1,0);
    118     for(int i=pl;pri[i]*pri[i]>=n;i--) ins(i,ed,1,0);
    119 }
    120 
    121 int main()
    122 {
    123     len=0;
    124     memset(first,0,sizeof(first));
    125     sum=0;
    126     scanf("%d",&n);
    127     init();
    128     max_flow();
    129     printf("%lld
    ",sum+1);
    130     return 0;
    131 }
    View Code

    有些东西不开LL会WA掉。

    2017-04-13 07:24:50

  • 相关阅读:
    面试题准备
    ImageList控件
    修改Visual Studio 2010 帮助文件库的位置
    委托与事件(续)
    PictureBox
    我的廣播情緣12/26
    回首我的2007 12/25
    水晶報表:列印支票金額12/12
    聖誕節快樂
    新年快樂
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6702180.html
Copyright © 2011-2022 走看看