zoukankan      html  css  js  c++  java
  • luogu P2515 [HAOI2010]软件安装 |Tarjan+树上背包

    题目描述

    现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为MM计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。

    但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为00。

    我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。

    输入格式

    第1行:N,M(0≤N≤100,0≤M≤500)

    第2行:W_1,W_2, ... W_i, ..., W_n

    第3行:V_1, V_2, ..., V_i, ..., V_n

    第4行:D_1, D_2, ..., D_i, ..., D_n

    输出格式

    一个整数,代表最大价值


    先把图缩点,变成树

    然后做树上背包

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define int long long
    using namespace std;
    const int N=505,M=10*N;
    int nxt[M],head[N],go[M],tot;
    inline void add(int u,int v){
    	nxt[++tot]=head[u];head[u]=tot;go[tot]=v;
    }
    int cost[N],val[N],d[N],f[N][N];
    int dfn[N],low[N],co[N],st[N],col,num,top;
    int c[N],va[N];
    inline void Tarjan(int u){
    	dfn[u]=low[u]=++num;
    	st[++top]=u;
    	for(int e=head[u];e;e=nxt[e]){
    		int v=go[e];
    		if(!dfn[v]){
    			Tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}
    		else if(!co[v])low[u]=min(low[u],dfn[v]);
    	}
    	if(dfn[u]==low[u]){
    		co[u]=++col;
    		while(st[top]!=u){ 
    			co[st[top]]=col;
    			--top;
    		}
    		--top;
    	}
    }
    int in[N];
    int n,m;
    inline void dfs(int u){
    	for(int i=c[u];i<=m;i++)f[u][i]=va[u];
    	for(int i=head[u];i;i=nxt[i]){
    		int v=go[i];
    		dfs(v);
    		for(int j=m-c[u];j>=0;j--)
    		for(int q=0;q<=j;q++)
    		f[u][j+c[u]]=max(f[u][j+c[u]],f[u][j+c[u]-q]+f[v][q]);
    	}
    }
    signed main(){
    	cin>>n>>m;
    	for(int i=1;i<=n;i++)scanf("%lld",&cost[i]);
    	for(int i=1;i<=n;i++)scanf("%lld",&val[i]);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&d[i]);
    		if(d[i])add(d[i],i);
    	}
    	for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i);
    	memset(nxt,0,sizeof(nxt)),memset(head,0,sizeof(head)),memset(go,0,sizeof(go)),tot=0;
    	for(int i=1;i<=n;i++){
    		c[co[i]]+=cost[i];
    		va[co[i]]+=val[i];
    		if(d[i]!=0&&co[i]!=co[d[i]])
    		add(co[d[i]],co[i]),in[co[i]]++;
    	}
    	int s=col+1;
    	for(int i=1;i<=col;i++)if(!in[i])add(s,i);
    	c[s]=0,va[s]=0; dfs(s);
    	cout<<f[s][m]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    pyspark 知识点
    pyspark 读取csv文件创建DataFrame的两种方法
    iOS开发改变字符串中指定字符颜色,大小等等
    iOS开发解决页面滑动返回跟scrollView左右划冲突
    iOS开发自定义试图切换
    iOS开发UIColor,CGColor,CIColor三者的区别和联系
    iOS开发热更新JSPatch
    Swift-创建UIButton(其他UI组件雷同)
    Swift-枚举enum理解
    Swift-闭包理解(二)
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/11853273.html
Copyright © 2011-2022 走看看