BZOJ 2427: [HAOI2010]软件安装( dp )

软件构成了一些树和一些环, 对于环我们要不不选, 要么选整个环. 跑tarjan缩点后, 新建个root, 往每个入度为0的点(强连通分量) 连边, 然后跑树dp( 01背包 )

----------------------------------------------------------------------------

#include<cstdio>

#include<cstring>

#include<stack>

#include<algorithm>

#include<vector>

#include<iostream>

#define rep(i, n) for(int i = 0; i < n; i++)

#define clr(x, c) memset(x, c, sizeof(x))

#define Rep(i, n) for(int i = 1; i <= n; ++i)

using namespace std;

const int maxn = 109, maxm = 509;

vector<int> G[maxn];

stack<int> S;

int dfn[maxn], low[maxn], scc[maxn], dfs_clock = 0, N = 0, n, m;

int W[maxn], V[maxn], w_t[maxn], v_t[maxn], d[maxn][maxm];

bool F[maxn];

void tarjan(int x) {

dfn[x] = low[x] = ++dfs_clock;

S.push(x);

for(vector<int>::iterator it = G[x].begin(); it != G[x].end(); it++)

if(!dfn[*it]) {

tarjan(*it);

low[x] = min(low[x], low[*it]);

} else if(!scc[*it])

low[x] = min(low[x], dfn[*it]);

if(low[x] == dfn[x]) {

N++;

int t;

do {

t = S.top(); S.pop();

scc[t] = N;

w_t[N] += W[t];

v_t[N] += V[t];

} while(t != x);

}

}

void TARJAN() {

clr(w_t, 0), clr(v_t, 0);

clr(scc, 0), clr(dfn, 0);

Rep(i, n) if(!dfn[i]) tarjan(i);

}

struct edge {

int to;

edge* next;

} E[maxn << 2], *pt = E, *head[maxn];

inline void add_edge(int u, int v) {

F[pt->to = v] = true;

pt->next = head[u];

head[u] = pt++;

}

void build() {

clr(F, 0), clr(head, 0);

Rep(i, n)

for(vector<int>::iterator it = G[i].begin(); it != G[i].end(); it++)

if(scc[*it] != scc[i]) add_edge(scc[i], scc[*it]);

Rep(i, N) if(!F[i])

add_edge(0, i);

}

void dp(int x) {

for(int i = v_t[x]; i <= m; i++) d[x][i] = w_t[x];

for(edge* e = head[x]; e; e = e->next) {

dp(e->to);

for(int h = m; h >= v_t[x]; h--)

for(int t = 0; t <= h - v_t[x]; t++)

d[x][h] = max(d[x][h], d[x][h - t] + d[e->to][t]);

}

}

int main() {

// freopen("test.in", "r", stdin);

cin >> n >> m;

Rep(i, n) scanf("%d", V + i);

Rep(i, n) scanf("%d", W + i);

Rep(i, n) {

int v;

scanf("%d", &v);

if(v) G[v].push_back(i);

}

TARJAN();

build();

clr(d, 0), dp(0);

cout << *max_element(d[0], d[0] + m + 1) << "\n";

return 0;

}

----------------------------------------------------------------------------

时间: 2024-10-09 22:28:24

BZOJ 2427: [HAOI2010]软件安装( dp )的相关文章

[Bzoj 2427] [HAOI2010] 软件安装 tarjan缩点+树形DP

题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一 些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的 是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出

bzoj 2427: [HAOI2010]软件安装

Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在

bzoj 2427: [HAOI2010]软件安装【tarjan+树形dp】

一眼最大权闭合子图,然后开始构图,画了画之后发现我其实是个智障网络流满足不了m,于是发现正确的打开方式应该是一眼树上dp 然后仔细看了看性质,发现把依赖关系建成图之后是个奇环森林,这个显然不能直接dp 发现这个环要选的话只能选整个环,所以tarjan缩一下点,然后再跑树上背包就行了 #include<iostream> #include<cstdio> #include<vector> #include<cstring> using namespace st

BZOJ2427: [HAOI2010]软件安装

2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1512  Solved: 584[Submit][Status][Discuss] Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j

P2515 [HAOI2010]软件安装

P2515 [HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关

HAOI2010软件安装(树形背包)

HAOI2010软件安装(树形背包) 题意 有n个物品,每个物品最多会依赖一个物品,但一个物品可以依赖于一个不独立(依赖于其它物品)的物品,且可能有多个物品依赖一个物品,并且依赖关系可能形成一个环.现给你V的资金,问如何分配资金,可以使你的得到的总价值最大,请求出这个总价值. 解法 我以前写过对于普通依赖性背包的博客:noip2006金明的预算方案如果对依赖性背包不是很熟悉的同学可以先看一下这道题. 由于这道题的依赖关系可能形成环,所以我们先用tarjan缩一下点,然后依赖关系图就变成了一个森林

【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包

[BZOJ2427][HAOI2010]软件安装 Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大).但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0.我们现在知道

HAOI2010 软件安装 有依赖的背包DP

题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一 些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的 是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出

BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP

题意: 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出一种方