#tarjan,樹形dp,dfs序#洛谷 2515 軟件安裝

題目


分析

題目乍一看不就是樹上揹包O(n2m)O(n^2m)嗎,再加個dfs序優化就可以O(nm)O(nm)了,其實不然,因爲有些軟件先行條件是會形成一個環的,所以還要用tarjan縮點,由於思路比較簡單,主要考碼題能力,所以就不多說了


代碼

#include <cstdio>
#include <cctype>
#include <cstring>
#include <stack>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=111; stack<int>stac;
struct node{int x,y,next;}e[N<<1],E[N];
int son[N],dfn[N],low[N],num,v[N],w[N],tw[N],mus[N],n,m,k=1,col[N],cnt,c[N],tc[N],ls[N],dp[N][N*5];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void tarjan(int x){
	dfn[x]=low[x]=++num;
	stac.push(x); v[x]=1;
	for (rr int i=ls[x];i;i=E[i].next)
	if (!dfn[E[i].y]){
		tarjan(E[i].y);
		low[x]=min(low[x],low[E[i].y]);
	}
	else if (v[E[i].y])
	    low[x]=min(low[x],dfn[E[i].y]);
	if (dfn[x]==low[x]){
		++cnt; rr int y;
		do{
			y=stac.top(),stac.pop();
			v[y]=0,col[y]=cnt,w[cnt]+=tw[y],c[cnt]+=tc[y];
		}while (x!=y);
	}
}
inline void add(int x,int y){e[++k]=(node){x,y,ls[x]},ls[x]=k;}
inline void dfs(int x){
	dfn[++num]=x,son[x]=1;
	for (rr int i=ls[x];~i;i=e[i].next)
	    mus[e[i].y]=mus[x]+w[x],dfs(e[i].y),son[x]+=son[e[i].y];
}
inline void Mx(int &x,int y){if (x<y) x=y;}
signed main(){
	n=iut(); m=iut();
	for (rr int i=1;i<=n;++i) tw[i]=iut();
	for (rr int i=1;i<=n;++i) tc[i]=iut();
	for (rr int i=1;i<=n;++i){
		rr int x=iut();
		if (x) E[i]=(node){x,i,ls[x]},ls[x]=i;
	}
	for (rr int i=1;i<=n;++i) if (!dfn[i]) tarjan(i);
	memset(ls,-1,sizeof(ls)); memset(dfn,0,sizeof(dfn));
	for (rr int i=1;i<=n;++i)
	if (E[i].x&&col[E[i].x]!=col[E[i].y])
	    v[col[E[i].y]]=1,add(col[E[i].x],col[E[i].y]);
	for (rr int i=1;i<=cnt;++i) if (!v[i]) add(0,i); num=0;
	dfs(0);
	for (rr int i=1;i<=num;++i){
		for (rr int j=mus[dfn[i]];j<=m-w[dfn[i]];++j)
		    Mx(dp[i+1][j+w[dfn[i]]],dp[i][j]+c[dfn[i]]);
		for (rr int j=mus[dfn[i]];j<=m;++j)
		    Mx(dp[i+son[dfn[i]]][j],dp[i][j]);
	}
	return !printf("%d\n",dp[num+1][m]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章