zoukankan      html  css  js  c++  java
  • [HAOI2010]软件安装[缩点 树形dp]

    [BZOJ2427] [luoguP2515]

    每个人都至多有一个依赖点 所以有可能成环 先tarjan缩点并处理出环的信息wei va

    再将缩点后的图重新连接 将入度为0的点和0点连接 这样就构成了一颗树

    由此做树形dp 只有父亲节点选了它的儿子才能选 所以在访问进去时先把wei[u]~m都赋为va[u] 我会说我又因为树形dp卡了半天吗

    #include<bits/stdc++.h>
    using namespace std;
    #define Max(x,y) ((x)>(y)?(x):(y))
    #define Min(x,y) ((x)<(y)?(x):(y))
    const int N=100+5,M=500+5,inf=0x3f3f3f3f,P=19650827;
    int n,m,in[N],w[N],val[N],f[N][M];
    template <class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    int head[N],tot=0;
    struct edge{int u,v,nxt;}e[N],E[N];
    void add(int u,int v){
    	e[++tot]=(edge){u,v,head[u]},head[u]=tot;
    }
    int idx=0,Bcnt=0,dfn[N],bl[N],low[N],wei[N],va[N];
    stack<int>s;bool inst[N];
    void tarjan(int u){
    	dfn[u]=low[u]=++idx;
    	s.push(u),inst[u]=1;
    	for(int i=head[u],v;i;i=e[i].nxt){
    		v=e[i].v;
    		if(!dfn[v]) tarjan(v),low[u]=Min(low[u],low[v]);
    		else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v];
    	}
    	if(low[u]==dfn[u]){
    		int v;++Bcnt;
    		do{
    			v=s.top(),s.pop();
    			inst[v]=0,bl[v]=Bcnt,wei[Bcnt]+=w[v],va[Bcnt]+=val[v];
    		}while(u!=v);
    	}
    }
    
    int hd[N],tt=0;
    void Add(int u,int v){
    	E[++tt]=(edge){u,v,hd[u]},hd[u]=tt;
    }
    void dfs(int u){
    	for(int i=wei[u];i<=m;++i) f[u][i]=va[u];
    	for(int i=hd[u],v;i;i=E[i].nxt){
    		v=E[i].v,dfs(v);
    		for(int j=m-wei[u];j>0;--j)
    		for(int k=0;k<=j;++k)
    		f[u][j+wei[u]]=Max(f[u][j+wei[u]],f[u][j+wei[u]-k]+f[v][k]);
    	}
    }
    
    int main(){
    //	freopen("in2.txt","r",stdin);
    	//freopen("xor.out","w",stdout);
    	rd(n),rd(m); 
    	for(int i=1;i<=n;++i) rd(w[i]);
    	for(int i=1;i<=n;++i) rd(val[i]);
    	for(int i=1,u;i<=n;++i){
    		rd(u);
    		if(u) add(u,i);
    	}
    	for(int i=1;i<=n;++i)
    	if(!dfn[i]) tarjan(i);
    	for(int i=1;i<=tot;++i)
    	if(bl[e[i].u]!=bl[e[i].v]) Add(bl[e[i].u],bl[e[i].v]),++in[bl[e[i].v]];
    	for(int i=1;i<=Bcnt;++i) if(!in[i]) Add(0,i);
    	memset(f,0,sizeof(f));dfs(0);
    	printf("%d",f[0][m]);
    	return 0;
    }
    
  • 相关阅读:
    正则表达式收藏
    c#mvc实现登录
    jQuery获取URL中的参数
    TortoiseSVN新人使用指南
    CheckBox获取一组及全选
    day45
    day44
    day43
    day43
    day42
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/11390563.html
Copyright © 2011-2022 走看看