对于软件的依赖可以转化为图上点之间的边的关系
发现对于一个强联通分量内的软件,一安则全安
Tarjan缩点
缩点后,从虚拟节点 0 向所有入度为 0 的点连边
这样就构成了一棵树
树形 dp
$dp[i][j]$ 表示对 $i$ 及其子树话费 $j$ 的价格所得到的收益
$dp[i][j] = dp[k][l] + dp[i][j - l]$

#include <bits/stdc++.h>

const int N = ;

int head[N], cnt;
struct Node {int u, v, nxt;};
int Tim, Bel[N], Low[N], Dfn[N], Stack[N], topp;
int W[N], V[N], Tw[N], Tv[N];
Node G[N];
int n, M;
bool vis[N];
int Gra; inline void Add(int u, int v) {G[++ cnt].v = v; G[cnt].nxt = head[u]; head[u] = cnt;} void Tarjan(int u) {
Dfn[u] = Low[u] = ++ Tim;
Stack[++ topp] = u, vis[u] = ;
for(int i = head[u]; ~ i; i = G[i].nxt) {
int v = G[i].v;
if(!Dfn[v]) {
Tarjan(v);
Low[u] = std:: min(Low[u], Low[v]);
} else if(vis[v]) Low[u] = std:: min(Low[u], Low[v]);
}
if(Low[u] == Dfn[u]) {
vis[u] = , Bel[u] = ++ Gra, Tw[Gra] += W[u], Tv[Gra] += V[u];
while(Stack[topp] != u) {
vis[Stack[topp]] = , Bel[Stack[topp]] = Gra, Tw[Gra] += W[Stack[topp]], Tv[Gra] += V[Stack[topp]];
topp --;
} topp --;
}
} int In[N], head_2[N];
Node E[N]; inline void Add2(int u, int v) {E[++ cnt].v = v, E[cnt].nxt = head_2[u], head_2[u] = cnt;} void Re_build() {
cnt = ;
for(int i = ; i <= Gra; i ++) head_2[i] = -;
for(int u = ; u <= n; u ++)
for(int i = head[u]; ~ i; i = G[i].nxt) {
int v = G[i].v;
if(Bel[u] != Bel[v]) Add2(Bel[u], Bel[v]), In[Bel[v]] = ;
}
} int f[N][N * ]; void Dfs(int u) {
for(int i = head_2[u]; ~ i; i = E[i].nxt) {
int v = E[i].v;
Dfs(v);
for(int j = M - Tw[u]; j >= ; j --)
for(int k = ; k <= j; k ++)
f[u][j] = std:: max(f[u][j], f[u][k] + f[v][j - k]);
}
for(int j = M; j >= ; j --) {
if(j >= Tw[u]) f[u][j] = f[u][j - Tw[u]] + Tv[u];
else f[u][j] = ;
}
} #define gc getchar() inline int read() {
int x = ; char c = gc;
while(c < '' || c > '') c = gc;
while(c >= '' && c <= '') x = x * + c - '', c = gc;
return x;
} int main() {
n = read(), M = read();
for(int i = ; i <= n; i ++) head[i] = -;
for(int i = ; i <= n; i ++) W[i] = read();
for(int i = ; i <= n; i ++) V[i] = read();
for(int i = ; i <= n; i ++) {
int u = read();
if(u) Add(u, i);
}
for(int i = ; i <= n; i ++) if(!Dfn[i]) Tarjan(i);
Re_build();
for(int i = ; i <= Gra; i ++) if(!In[i]) Add2(, i);
Dfs();
std:: cout << f[][M];
return ;
}

luogu 2515的更多相关文章

  1. Luogu 魔法学院杯-第二弹(萌新的第一法blog)

    虽然有点久远  还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题  沉迷游戏,伤感情 #include <queue> ...

  2. luogu p1268 树的重量——构造,真正考验编程能力

    题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...

  3. [luogu P2170] 选学霸(并查集+dp)

    题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...

  4. [luogu P2647] 最大收益(贪心+dp)

    题目传送门:https://www.luogu.org/problem/show?pid=2647 题目描述 现在你面前有n个物品,编号分别为1,2,3,--,n.你可以在这当中任意选择任意多个物品. ...

  5. Luogu 考前模拟Round. 1

    A.情书 题目:http://www.luogu.org/problem/show?pid=2264 赛中:sb题,直接暴力匹配就行了,注意一下读入和最后一句话的分句 赛后:卧槽 怎么只有40 B.小 ...

  6. luogu P2580 于是他错误的点名开始了

    luogu  P2580 于是他错误的点名开始了 https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边 ...

  7. CJOJ 1331 【HNOI2011】数学作业 / Luogu 3216 【HNOI2011】数学作业 / HYSBZ 2326 数学作业(递推,矩阵)

    CJOJ 1331 [HNOI2011]数学作业 / Luogu 3216 [HNOI2011]数学作业 / HYSBZ 2326 数学作业(递推,矩阵) Description 小 C 数学成绩优异 ...

  8. Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂)

    Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂) Description 广义的斐波那契数列是指形如\[A_n=p*a_{n-1}+q*a_{n-2}\]的数列.今给定数列的两系数p和q, ...

  9. Luogu 1962 斐波那契数列(矩阵,递推)

    Luogu 1962 斐波那契数列(矩阵,递推) Description 大家都知道,斐波那契数列是满足如下性质的一个数列: f(1) = 1 f(2) = 1 f(n) = f(n-1) + f(n ...

随机推荐

  1. BZOJ4199 NOI2015品酒大会(后缀树)

    利用SAM建出后缀树,树上每个节点计算一下|right|.right集合中ai的最大.次大.最小.次小值即可. #include<iostream> #include<cstdio& ...

  2. This is very likely to create a memory leak. Stack trace of thread错误分析

    1.问题描述 启动tomcat部署项目时,报This is very likely to create a memory leak. Stack trace of thread错误. 29-May-2 ...

  3. jacascript Math (算数)对象

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 实际应用中用的比较多的有:round(); random(); floor(); ceil(); 其次还有 ...

  4. qt连接oracle数据库

    由与qt开源版本没有提供oracle数据库驱动,需要自己根据源代码来手动编译oracle驱动. 经过近三天的折腾,终于成功编译oracle驱动,连接到数据库 ps:期间经过各种失败疼苦迷茫.现在终于完 ...

  5. JS数组抽奖程序教学实例

    数组Javascript中非常重要的知识点,为了在课堂上提高学生兴趣,教学举例的选择就比较重要了. 为了提高学生兴趣,特设计一个可输入,可控制结束的,利用JS数组实现的抽奖教学实例.代码如下:

  6. c#界面卡死处理方法

    方法一: 设置属性: Control.CheckForIllegalCrossThreadCalls = false; 开启一个新线程 Thread th = new Thread(() => ...

  7. 34. Find First and Last Position of Element in Sorted Array + 二分

    题意懒得抄了,大概是:在升序数组中给定整数target,找到第一个和最后一个target的索引,找到返回{index1, index2},否则返回{-1, -1}: 时间复杂度要求:O(logn) 分 ...

  8. java序列化和反序列化使用总结

    一.概念 java对象序列化的意思就是将对象的状态转化成字节流,以后可以通过这些值再生成相同状态的对象.对象序列化是对象持久化的一种实现方法,它是将对象的属性和方法转化为一种序列化的形式用于存储和传输 ...

  9. stm32f429 仿真器不能识别芯片

    刚买的野火挑战者开发板,下载几次程序后,忽然就不能通过JLINK下载了,提示如下错误: No Cortex-M Device found in JTAG chain. Error: Flash Dow ...

  10. 用js刷剑指offer(旋转数组的最小数字)

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个 ...