zoukankan      html  css  js  c++  java
  • [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;
    }
    

  • 相关阅读:
    windows RabbitMQ Server 环境配置中的一些坑
    Redis自定义fastJson Serializer
    如何使用Feign构造多参数的请求
    跨域访问支持(Spring Boot、Nginx、浏览器)
    chrome浏览器的跨域设置
    Jenkins手把手图文教程[基于Jenkins 2.164.1]
    Spring Boot 2发送邮件手把手图文教程
    poi读取Excel模板并修改模板内容与动态的增加行
    Lock类-ReentrantLock的使用
    类ThreadLocal的使用与源码分析
  • 原文地址:https://www.cnblogs.com/Troverld/p/14596927.html
Copyright © 2011-2022 走看看