【HAOI2010】【强连通分量】【树形动态规划】软件安装

来源:互联网 发布:com域名与cn域名 编辑:程序博客网 时间:2024/05/29 11:06

这道题是一道水题。。。

由于软件的依赖关系可能是一个环,所以先将原图缩点。

将缩点后的树转化为二叉树后f[i][j]表示以i为跟的子树分配j的空间得到的最大价值l[i],r[i]表示i的左儿子和右儿子

f[i][j] = max(f[r[i]][j],f[l[i]][k] + f[r[i]][j - k - w[i]] + v[i])

使用记忆化实现。

代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 100 + 10;const int maxm = 500 + 10;struct tree{int l,r;tree(){l = r = -1;}}Tree[maxn];struct pnode{int pos;pnode *next;pnode(){}pnode(int pos,pnode *next):pos(pos),next(next){}}*first[maxn],__[maxn],*tot = __;int w[maxn],v[maxn],nw[maxn],nv[maxn];int dfn[maxn],low[maxn],stack[maxn];int belong[maxn],dig[maxn];int f[maxn][maxm];bool instack[maxn],map[maxn][maxn];int step = 0,stop = 0,cnt = 0;int n,m;void init(){freopen("bzoj2427.in","r",stdin);freopen("bzoj2427.out","w",stdout);}void readdata(){scanf("%d%d",&n,&m);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;i <= n;i++){int tmp;scanf("%d",&tmp);first[tmp] = new(tot++)pnode(i,first[tmp]);}}void tarjan(int u){dfn[u] = low[u] = ++step;stack[stop++] = u;instack[u] = true;for(pnode *p = first[u];p != NULL;p = p -> next){int v = p -> pos;if(!dfn[v]){tarjan(v);if(low[v] < low[u])low[u] = low[v];}else if(instack[v] && dfn[v] < low[u])low[u] = dfn[v];}if(dfn[u] == low[u]){cnt++;int tmp;do{tmp = stack[--stop];instack[tmp] = false;belong[tmp] = cnt;nw[cnt] += w[tmp];nv[cnt] += v[tmp];}while(tmp != u);}}void build_map(){for(int u = 1;u <= n;u++){for(pnode *p = first[u];p != NULL;p = p -> next){int v = p -> pos;if(belong[u] != belong[v]){++dig[belong[v]];map[belong[u]][belong[v]] = true;}}}}void build_tree(int k){for(int i = 1;i <= cnt;i++){if(map[k][i]){if(Tree[k].l == -1)Tree[k].l = i;else{int t = Tree[k].l;while(Tree[t].r != -1)t = Tree[t].r;Tree[t].r = i;}}}if(Tree[k].l != -1)build_tree(Tree[k].l);if(Tree[k].r != -1)build_tree(Tree[k].r);}int dfs(int d,int k){if(d == -1)return 0;if(f[d][k] != -1)return f[d][k];f[d][k] = dfs(Tree[d].r,k);for(int i = 0;i <= k - nw[d];i++){f[d][k] = max(f[d][k],dfs(Tree[d].l,i) + dfs(Tree[d].r,k - i - nw[d]) + nv[d]);}return f[d][k];}void solve(){memset(f,-1,sizeof(f));step = stop = 0;for(int i = 1;i <= n;i++){if(!dfn[i])tarjan(i);}build_map();for(int i = 1;i <= cnt;i++){if(!dig[i])map[0][i] = true;}build_tree(0);printf("%d\n",dfs(0,m));}int main(){init();readdata();solve();return 0;}


原创粉丝点击