2427: [HAOI2010]软件安装

来源:互联网 发布:网络推广专员薪资制度 编辑:程序博客网 时间:2024/06/07 00:37

连接:点击打开链接

因为可能有环,即要么一起选,要么都不选,做一期强联通缩点,在树上dp即可。

注意,每个点做完要延父亲边更新一次。

code:

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>using namespace std;int w[210],v[210],d[210],f[510][210],g[210],n,m;int dfn[110],low[110],id,top,sta[110],belong[110],cnt=0;bool u[110];struct node{int y,next;}a[210];int last[210],len=0;void ins(int x,int y){a[++len].y=y;a[len].next=last[x];last[x]=len;}void dp(int x){g[x]=g[d[x]]+w[x];for(int i=m;i>=g[x];i--)f[i][x]=max(f[i][x],f[i-w[x]][d[x]]+v[x]);for(int i=last[x];i;i=a[i].next) dp(a[i].y);int fa=d[x];while(1){for(int i=0;i<=m;i++) f[i][fa]=max(f[i][fa],f[i][x]);if(fa==0) break;fa=d[fa];}}void dfs(int x){dfn[x]=low[x]=++id;sta[++top]=x;u[x]=true;if(d[x]!=0){int y=d[x];if(dfn[y]==-1){dfs(y);low[x]=min(low[x],low[y]);}elseif(u[y]) low[x]=min(low[x],dfn[y]);}if(low[x]==dfn[x])    {        cnt++;int i;        do{        i=sta[top--];w[cnt]+=w[i];v[cnt]+=v[i];        u[i]=false;        belong[i]=cnt;        }while(i!=x);    }}int main(){scanf("%d %d",&n,&m);cnt=n;for(int i=1;i<=n;i++) scanf("%d",&w[i]);for(int i=1;i<=n;i++) scanf("%d",&v[i]);for(int i=1;i<=n;i++) scanf("%d",&d[i]);memset(dfn,-1,sizeof(dfn));memset(u,false,sizeof(u));id=top=0;for(int i=1;i<=n;i++)if(dfn[i]==-1) dfs(i);for(int i=1;i<=n;i++){if(belong[i]!=belong[d[i]])d[belong[i]]=belong[d[i]],ins(belong[d[i]],belong[i]);}for(int i=n+1;i<=cnt;i++) if(d[i]==0) dp(i);printf("%d",f[m][0]);}


原创粉丝点击