[ARC085]E

来源:互联网 发布:苏亚雷斯实况巅峰数据 编辑:程序博客网 时间:2024/06/14 18:39

题面
考虑第x个数没有被筛去,那么x的约数都应该没有被筛去。
所以每个点的点权就是它的价值,然后向自己所有约数连边,跑最大权闭合子图即可。
代码:

#include<iostream>#include<cstdio>#include<cstring>#define ll long longusing namespace std;int n,a[110],S,T,ne[110],dl[110];bool vis[110];ll ans=0;struct edge{    int t;    ll c,f;    edge *next,*rev;}*con[110];void ins(int x,int y,ll c){    edge *p=new edge;    p->t=y;    p->c=c;    p->f=0;    p->next=con[x];    con[x]=p;    p=new edge;    p->t=x;    p->c=0;    p->f=0;    p->next=con[y];    con[y]=p;    con[x]->rev=con[y];    con[y]->rev=con[x];}bool bfs(){    int head,tail;bool re=0;    memset(ne,0,sizeof(ne));    dl[1]=S;ne[S]=1;    for(head=tail=1;head<=tail;head++)    {           int v=dl[head];        if(v==T) re=1;        for(edge *p=con[v];p;p=p->next)            if(!ne[p->t]&&p->c>p->f)                ne[p->t]=ne[v]+1,dl[++tail]=p->t;       }    return re;}ll dinic(int v,ll flow){    if(v==T) return flow;    if(vis[v]) return 0;    ll re=0;    for(edge *p=con[v];flow&&p;p=p->next)        if(ne[p->t]==ne[v]+1&&p->c>p->f)        {            ll o=dinic(p->t,min(flow,p->c-p->f));            p->f+=o;p->rev->f-=o;            re+=o;flow-=o;         }    if(re==0) vis[v]=1;    return re;      }int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]);    S=0;T=n+1;    for(int i=1;i<=n;i++)        if(a[i]>0) ins(S,i,a[i]),ans+=a[i];        else         {            ins(i,T,-a[i]);            for(int j=2;i*j<=n;j++)                if(a[i*j]>0) {ins(i*j,i,1e15);}        }    while(bfs())    {        memset(vis,0,sizeof(vis));        ans-=dinic(S,1e15);    }    printf("%lld",ans);    return 0;}