【BZOJ2427】【HAOI2010】软件安装 tarjan+树形背包DP

来源:互联网 发布:报表软件制作 编辑:程序博客网 时间:2024/05/20 22:38

链接:

#include <stdio.h>int main(){    puts("转载请注明出处[vmurder]谢谢");    puts("网址:blog.csdn.net/vmurder/article/details/44655217");}

题解:

首先它可能有环。所以先tarjan缩点。
然后跑树形背包。

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 120#define M 600using namespace std;struct Eli{    int v,next;}e[M];int head[N],cnt;inline void add(int u,int v){    e[++cnt].v=v;    e[cnt].next=head[u];    head[u]=cnt;}int value[N],occupy[N],depend[N];int Value[N],Occupy[N];// trajan大法好!int dfn[N],low[N],stk[N],top;int id[N],group;bool ins[N];void trajan(int x){    dfn[x]=low[x]=++cnt;    stk[++top]=x,ins[x]=1;    int i,v;    for(i=head[x];i;i=e[i].next)    {        v=e[i].v;        if(!dfn[v])        {            trajan(v);            low[x]=min(low[x],low[v]);        }        else if(ins[v])low[x]=min(low[x],dfn[v]);;    }    if(low[x]==dfn[x])    {        group++;        do{            v=stk[top--];            ins[v]=0;            id[v]=group;            Value[group]+=value[v];            Occupy[group]+=occupy[v];        }while(v!=x);    }}int f[N][M],ans;int n,m;void Tree_DP(int x,int p){    int i,j,k,v;    for(j=m;j>=Occupy[x];j--)f[x][j]=Value[x];    for(i=head[x];i;i=e[i].next)    {        v=e[i].v;        if(v==p)continue;        Tree_DP(v,x);        for(j=m-Occupy[x];j>=0;j--)for(k=1;k<=j;k++)            f[x][j+Occupy[x]]=max(f[x][j+Occupy[x]],f[x][j+Occupy[x]-k]+f[v][k]);    }}int g[M];int main(){//  freopen("test.in","r",stdin);    int i,j,k;    int a,b,c;    scanf("%d%d",&n,&m);    for(i=1;i<=n;i++)scanf("%d",&occupy[i]);    for(i=1;i<=n;i++)scanf("%d",&value[i]);    for(i=1;i<=n;i++)    {        scanf("%d",&depend[i]);        if(depend[i])add(depend[i],i);    }cnt=0;    for(i=1;i<=n;i++)if(!dfn[i])trajan(i);    memset(head,0,sizeof head),cnt=0;    for(i=1;i<=n;i++)if(depend[i]&&id[depend[i]]!=id[i])        add(id[depend[i]],id[i]),ins[id[i]]=1;    for(i=1;i<=group;i++)if(!ins[i])    {        Tree_DP(i,0);        for(j=m;j;j--)for(k=1;k<=j;k++)            g[j]=max(g[j],g[j-k]+f[i][k]);    }    for(i=0;i<=m;i++)ans=max(ans,g[i]);    printf("%d\n",ans);    return 0;}
0 0
原创粉丝点击