zoukankan      html  css  js  c++  java
  • 题解:Luogu P2515 [HAOI2010]软件安装

    题面

    本文主要来记录一个没见过的树形背包 DP 写法

    这题是个裸的 tarjan 缩点和树形背包 DP

    显然循环依赖就缩成一点再进行 DP 即可

    (f(i,j)) 为 dfs 序中第 i 个点及以后占用磁盘空间为 j 的连通块的最大价值

    (f(i,j)=max {f(i+1,j-W[i])+V[i],f(i+size_{dfn_i},j)})

    时间复杂度 (mathcal{O}(n imes m))

    Code(C++):

    #include<bits/stdc++.h>
    #define forn(i,s,t) for(int i=(s);i<=(t);++i)
    #define form(i,s,t) for(int i=(s);i>=(t);--i)
    using namespace std;
    const int N = 105,M = 505,INF = 1e9+7;
    template<typename T>
    inline void chkmax(T &A,T B) {A=A>B?A:B;}
    struct List {
    	int dir,nxt;
    }E[N],T[N];
    int G[N],cnt,cntt,GT[N],dT[N];
    inline void Add(int u,int v) {
    	E[++cnt].dir = v,E[cnt].nxt = G[u],G[u] = cnt;
    }
    inline void AddT(int u,int v) {
    	T[++cntt].dir = v,T[cntt].nxt = GT[u],GT[u] = cntt,dT[v] ++ ;
    }
    int n,m,w[N],v[N],d[N],dn[N],stk[N],h,ord,clr[N],col,W[N],V[N];
    bool vis[N];
    int tarjan(int u) {
    	int low = dn[u] = ++ord;
    	stk[++h] = u,vis[u] = 1;
    	for(int i=G[u];i;i=E[i].nxt) {
    		int v = E[i].dir;
    		if(!dn[v]) low = min(tarjan(v),low);
    		else if(vis[v]) low = min(low,dn[v]);
    	}
    	if(low == dn[u]) {
    		++col;
    		do clr[stk[h]]=col,W[col]+=w[stk[h]],V[col]+=v[stk[h]],vis[stk[h]]=0;
    		while(stk[h--]!=u);
    	}
    	return low;
    }
    int f[N][M],sz[N],rk[N];
    void dfs(int u) {
    	sz[u] = 1,rk[++ord] = u;
    	for(int i=GT[u];i;i=T[i].nxt) {
    		int v = T[i].dir;
    		dfs(v),sz[u] += sz[v];
    	}
    }
    int main() {
    	scanf("%d%d",&n,&m);
    	forn(i,1,n) scanf("%d",&w[i]);
    	forn(i,1,n) scanf("%d",&v[i]);
    	forn(i,1,n) scanf("%d",&d[i]),d[i]?(Add(d[i],i),0):0;
    	forn(i,1,n) if(!dn[i]) tarjan(i);
    	forn(u,1,n) for(int i=G[u];i;i=E[i].nxt) {
    		int v = E[i].dir;
    		if(clr[u]!=clr[v]) AddT(clr[u],clr[v]);
    	}
    	forn(u,1,col) if(!dT[u]) AddT(0,u);
    	ord = 0,dfs(0);
    	form(i,ord,1) { int u = rk[i];
    		forn(j,0,m) {
    			chkmax(f[i][j],f[i+sz[u]][j]);
    			if(j>=W[u]) chkmax(f[i][j],f[i+1][j-W[u]]+V[u]);
    		}
    	}
    	printf("%d
    ",f[1][m]);
    	return 0;
    }
    
  • 相关阅读:
    一笔期货成交的始末(可能有问题)
    tcp心跳模型
    spring boot 2.0 启动监控端点的方法(spring-boot-starter-actuator)
    netty channel的线程安全性与@Sharable
    为什么使用https
    angularjs post 跨域 Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
    http的keep-alive和tcp的keepalive区别
    最大公约数 最小公倍数--------专题
    hdu 2024 C语言合法标识符
    hdu 2025 查找最大元素
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/14077032.html
Copyright © 2011-2022 走看看