bzoj 3308: 九月的咖啡店【最大费用最大流】

费用流里spfa最后的判断要写成dis[t]>=0而不是dis[t]!=-inf否则会WAWAWA……

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=200005,inf=1e9;
int n,tot,s,t,ans,dis[N],h[N],cnt=1,p[N],fr[N];
bool v[N];
struct qwe
{
    int ne,no,to,va,c;
}e[N*10];
void add(int u,int v,int w,int c)
{
    cnt++;
    e[cnt].ne=h[u];
    e[cnt].no=u;
    e[cnt].to=v;
    e[cnt].va=w;
    e[cnt].c=c;
    h[u]=cnt;
}
void ins(int u,int v,int w,int c)
{
    add(u,v,w,c);
    add(v,u,0,-c);
}
bool spfa()
{
    for(int i=s;i<=t;i++)
        dis[i]=-inf;
    memset(v,0,sizeof(v));
    queue<int>q;
    dis[s]=0;
    v[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        v[u]=0;
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].va&&dis[u]+e[i].c>dis[e[i].to])
            {
                dis[e[i].to]=dis[u]+e[i].c;
                fr[e[i].to]=i;
                if(!v[e[i].to])
                {
                    v[e[i].to]=1;
                    q.push(e[i].to);
                }
            }
    }
    return dis[t]>=0;
}
void mcf()
{
    int x=inf;
    for(int i=fr[t];i;i=fr[e[i].no])
        x=min(x,e[i].va);
    for(int i=fr[t];i;i=fr[e[i].no])
    {
        e[i].va-=x;
        e[i^1].va+=x;
        ans+=x*e[i].c;
    }
}
int clc(int n,int x)
{
    long long t=x;
    while(t*x<=n)
        t*=x;
    return t;
}
int main()
{
    scanf("%d",&n);
    for(int i=2;i<=n;i++)
    {
        if(!v[i])
            p[++tot]=i;
        for(int j=1;j<=tot&&p[j]*i<=n;j++)
        {
            v[i*p[j]]=1;
            if(i%p[j]==0)
                break;
        }
    }
    s=0,t=tot+1;
    int pos=0;
    for(int i=1;i<=tot;i++)
    {
        if(p[i]>=n/2)
        {
            ans+=p[i];
            continue;
        }
        if((long long)p[i]*p[i]<=n)
        {
            ins(s,i,1,0);
            ans+=clc(n,p[i]);
        }
        else
        {
            if(!pos)
                pos=i;
            ins(i,t,1,0);
            ans+=p[i];
        }
    }
    for(int i=1;i<pos;i++)
        for(int j=pos;j<=tot;j++)
        {
            if((long long)p[i]*p[j]>n)
                break;
            int nw=clc(n/p[j],p[i])*p[j]-clc(n,p[i])-p[j];
            if(nw>0)
                ins(i,j,1,nw);
        }
    while(spfa())
        mcf();
    printf("%d\n",ans+1);
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/9690338.html

时间: 2024-10-03 16:11:49

bzoj 3308: 九月的咖啡店【最大费用最大流】的相关文章

【BZOJ 3308】 3308: 九月的咖啡店 (费用流|二分图最大权匹配)

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

【BZOJ-3308】九月的咖啡店 最大费用最大流 + 线性筛素数

3308: 九月的咖啡店 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 159  Solved: 56[Submit][Status][Discuss] Description 深绘里在九份开了一家咖啡让,如何调配咖啡民了她每天的头等大事我们假设她有N种原料,第i种原料编号为i,调配一杯咖啡则需要在这里若干种兑在一起.不过有些原料不能同时在一杯中,如果两个编号为i,j的原料,当且仅当i与j互质时,才能兑在同一杯中.现在想知道,如果用这N种原料来调

BZOJ 3308 九月的咖啡店 费用流

题目大意:在[1,n]区间内选择一些数,使得这些数两两互质,求这些数的和的最大值 容易发现对于一个最优解,每个质数存在且仅存在于一个数中.(废话. 但是有可能一个数中存在多个质数 下面是两个结论: 1.一个数中最多存在两个不同的质数 2.这两个质数一个<n√,一个>n√ 我完全不会证明这两个结论,这两个结论都是官方题解里的 然后就好办了,我们对于<n√的质数和>n√的质数建立二分图,求最大费用最大流即可 但是这样会T掉,因为图太大了 因此我们有两个剪枝: 1.对于>n2的质数

BZOJ 1449 球队收益(最小费用最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1449 题意: 思路:首先,我们假设后面的M场比赛两方都是输的,即初始时的lose[i]再加上i参加的场次.这样,后面对于i,每赢一场的收益增加值为: 之后win[i]++,lose[i]--.至此,我们得到建图的方法: (1)源点到每场比赛连流量1,费用0: (2)每场比赛向双方连流量1,费用0: (3)每个人到汇点连x条边(x为该人在M场比赛中出现的次数),流量1,费用为上面计算出的

BZOJ 1061 志愿者招募(最小费用最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061 题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人. 布布通过了解得知,一共有M 类志愿者可以招募.其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元.新官上任三把火,为了出色地完成自己的工作,布

BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流

传送门 BZOJ 2668 题解 同时分别限制流入和流出次数,所以把一个点拆成三个:入点in(x).中间点mi(x).出点ou(x). 如果一个格子x在初始状态是黑点,则连(S, mi(x), 1, 0) 如果x在目标状态是黑点,则连(mi(x), T, 1, 0) 设x的交换次数限制是w 如果x在两种状态中颜色相同,则连(in(x), mi(x), w / 2, 0), (mi(x), ou(x), w / 2, 0) 如果x只在初始状态为黑色,则连(in(x), mi(x), w / 2,

BZOJ 1221: [HNOI2001] 软件开发(最小费用最大流)

不知道为什么这么慢.... 费用流,拆点.... -------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #define rep( i, n ) for( int

BZOJ 1877: [SDOI2009]晨跑( 最小费用最大流 )

裸的费用流...拆点, 流量限制为1, 最后的流量和费用即答案. ---------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; const int maxn = 409; const int INF = 1 << 30; struct edge { int to, cap, cost; edge *next, *r

BZOJ 1927: [Sdoi2010]星际竞速(最小费用最大流)

拆点,费用流... ----------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #define rep( i, n ) for( int i = 0; i < n; +