• [HAOI2010]软件安装


    XVIII.[HAOI2010]软件安装

    不知道大家有没有做过这道题[CTSC1997]选课啊,反正我一看到这道题,就想起了它——都是树上背包。所以我便高高兴兴的敲了一发背包交上去。

    然后呢?光荣的WA掉了。

    为什么呢?

    因为这道题和选课不一样;选课是你没有修完前一节课就不能修这节;但是本题是你装软件是可以随便装,想咋装就咋装的——只不过会不会起效就不知道了。因此,如果成环的话,只要整个环全装上就行了。

    那么我们就SCC缩个点,在缩出来的树上背包一下就行了(实际上数据还可以加强成DAG的……)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,w[110],v[110],f[110][510],g[510],res,col[110],val[110],sz[110],in[110],c;
    namespace SCC{
    	int tot,dfn[310],low[310],head[310],cnt;
    	struct node{
    		int to,next;
    	}edge[200100];
    	void ae(int u,int v){
    	//	cout<<u<<" "<<v<<endl;
    		edge[cnt].next=head[u],edge[cnt].to=v,head[u]=cnt++;
    	}
    	stack<int>stk;
    	void Tarjan(int x){
    		dfn[x]=low[x]=++tot,stk.push(x);
    		for(int i=head[x];i!=-1;i=edge[i].next){
    			if(!dfn[edge[i].to])Tarjan(edge[i].to),low[x]=min(low[x],low[edge[i].to]);
    			if(!col[edge[i].to])low[x]=min(low[x],dfn[edge[i].to]);
    		}
    		if(low[x]<dfn[x])return;
    		c++;
    		while(stk.top()!=x)col[stk.top()]=c,val[c]+=v[stk.top()],sz[c]+=w[stk.top()],stk.pop();
    		col[stk.top()]=c,val[c]+=v[stk.top()],sz[c]+=w[stk.top()],stk.pop();
    	}
    }
    namespace DP{
    	int head[110],cnt;
    	struct node{
    		int to,next;
    	}edge[110];
    	void ae(int u,int v){
    //		printf("%d %d\n",u,v);
    		edge[cnt].next=head[u],edge[cnt].to=v,head[u]=cnt++;
    	}
    	void dfs(int x){
    		if(sz[x]<=m)f[x][sz[x]]=val[x];
    		for(int i=head[x];i!=-1;i=edge[i].next){
    			dfs(edge[i].to);
    			for(int j=0;j<=m;j++)g[j]=f[x][j];
    			for(int j=0;j<=m;j++)for(int k=0;j+k<=m;k++)if(f[x][j]!=-1&&f[edge[i].to][k]!=-1)g[j+k]=max(g[j+k],f[x][j]+f[edge[i].to][k]);
    			for(int j=0;j<=m;j++)f[x][j]=g[j];
    		}
    	}	
    }
    int main(){
    	scanf("%d%d",&n,&m),memset(f,-1,sizeof(f)),memset(SCC::head,-1,sizeof(SCC::head)),memset(DP::head,-1,sizeof(DP::head));
    	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,x;i<=n;i++){
    		scanf("%d",&x);
    		if(x)SCC::ae(x,i);
    	}
    	for(int i=1;i<=n;i++)if(!SCC::dfn[i])SCC::Tarjan(i);
    //	for(int i=1;i<=c;i++)printf("%d %d\n",val[i],sz[i]);
    	for(int i=1;i<=n;i++)for(int j=SCC::head[i];j!=-1;j=SCC::edge[j].next)if(col[i]!=col[SCC::edge[j].to])DP::ae(col[i],col[SCC::edge[j].to]),in[col[SCC::edge[j].to]]++;
    	for(int i=1;i<=c;i++)if(!in[i])DP::ae(0,i);
    	DP::dfs(0);
    	for(int i=0;i<=m;i++)res=max(res,f[0][i]);
    	printf("%d\n",res);
    	return 0;
    }
    

  • 相关阅读:
    代码规范圣战
    代码复审结果
    个人工程总结
    第一周个人博客作业
    软工课程总结
    软件工程课程的建议
    大泥球你好~
    第一次会议记录
    软件工程的瀑布, 大泥球, 教堂,集市,和银弹
    vs2013——单元测试&& 性能图
  • 原文地址:https://www.cnblogs.com/Troverld/p/14596927.html
Copyright © 2020-2023  润新知