http://codeforces.com/gym/100502/attachments

题意:有n个点,容量为tol,接下来n个关系,表示选了第i个点,那么第xi个点就必须被选。问最多可以选多少个点使得不超过容量tol。

思路:由题目样例可得,边可能出现自环的情况,这个时候这条边其实没用。然后因为是一个图,所以需要缩点,缩完之后用一个sz数组表示点的大小,重新建一幅图。因为有可能是森林,所以需要添加一个虚根,使得其变成一棵树。然后题目就转变为求有依赖的树上背包了。

我是学了这篇博客的写法:http://blog.csdn.net/y990041769/article/details/38068223

dp[i][j]表示以i为根的子树在容量为j的时候能放的点的最大个数。sz[i]表示i结点的大小。

因为i是必须选的(不然其儿子都没办法选),那么一开始就直接赋予其值。

         for(int j = tol; j >= sz[u]; j--) { // 枚举容量
for(int k = ; k <= j - sz[u]; k++) { // k表示能分配给子节点的容量
dp[u][j] = max(dp[u][j], dp[u][j-k] + dp[v][k]);
}
}

接下来第一层循环是像01背包一样,枚举能够放下u(根结点)自己的容量,第二层循环k代表能够分配给儿子的容量,因为根结点自己已经放进去了,所以是j-sz[u]。就这样可以更新完u这个根节点了。

 #include <bits/stdc++.h>
using namespace std;
#define N 1010
struct Edge {
int v, nxt;
} edge[N*], e[N*];
int n, tol, head[N], tot, h[N], t, dfn[N], low[N], belong[N], vis[N], num, tid, sz[N], deg[N], dp[N][N];
stack<int> sta; void Add(int u, int v) { edge[tot] = (Edge) {v, head[u]}; head[u] = tot++; }
void add(int u, int v) { e[t] = (Edge) {v, h[u]}; h[u] = t++; } void tarjan(int u) {
sta.push(u);
vis[u] = ;
dfn[u] = low[u] = ++tid;
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(vis[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u]) {
num++;
int top = -;
while(top != u) {
top = sta.top(); sta.pop();
belong[top] = num;
sz[num]++;
vis[top] = ;
}
}
} void BuildGraph() {
memset(head, -, sizeof(head));
memset(h, -, sizeof(h));
t = tot = ;
for(int i = ; i <= n; i++) {
int j; scanf("%d", &j);
if(i == j) continue;
Add(j, i);
}
for(int i = ; i <= n; i++)
if(!dfn[i]) tarjan(i); // 将环缩点重新建图
for(int u = ; u <= n; u++) {
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(belong[u] != belong[v]) {
add(belong[u], belong[v]);
deg[belong[v]]++;
}
}
}
for(int i = ; i <= num; i++) // 设一个虚根将森林变成树
if(!deg[i]) add(, i);
} void dfs(int u) {
for(int i = tol; i >= sz[u]; i--) dp[u][i] = sz[u]; // 初始状态必须有这个结点的sz
for(int i = h[u]; ~i; i = e[i].nxt) {
int v = e[i].v;
dfs(v);
for(int j = tol; j >= sz[u]; j--) { // 枚举容量
for(int k = ; k <= j - sz[u]; k++) { // k表示能分配给子节点的容量
dp[u][j] = max(dp[u][j], dp[u][j-k] + dp[v][k]);
}
}
}
} void Bag() {
dfs();
printf("%d\n", dp[][tol]);
} int main() {
scanf("%d%d", &n, &tol);
BuildGraph();
Bag();
return ;
}

Codeforces Gym100502G:Outing(缩点+有依赖的树形背包)的更多相关文章

  1. 一类有依赖的树形背包dp方法

    失踪人口回归系列 这个标题是不是看起来很厉害呢233 给一道例题:有一个树,每一个节点代表一个物品,每个物品有重量和价值,每个物品必须先选父亲才能选自己.求给定重量内最大价值. 这题的思路十分的厉害. ...

  2. 【洛谷 P2515】 [HAOI2010]软件安装 (缩点+树形背包)

    题目链接 看到代价和价值这两个关键词,肯定是首先要想到背包的. 但是图中并没有说这是棵树,所以先要\(Tarjan\)缩点,然后就是选课了,跑一遍树形背包就好了. 注意:缩点后应该是一个森林,应该用一 ...

  3. 洛谷 P1064 金明的预算方案【有依赖的分组背包】

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱 ...

  4. We Need More Bosses CodeForces - 1000E (无向图缩点)

    大意: 给定无向连通图, 定义两个点$s,t$个价值为切断一条边可以使$s,t$不连通的边数. 求最大价值. 显然只有桥会产生贡献. 先对边双连通分量缩点建树, 然后求直径即为答案. #include ...

  5. Cactus CodeForces - 231E (无向图缩环)

    大意: 给定无向图, 每个点最多属于一个简单环, 多组询问, 求给定起点终点, 有多少条简单路径. 先缩环, 然后假设两点树上路径经过$cnt$个环, 那么答案就为$2^{cnt}$. 要注意缩环建树 ...

  6. We Need More Bosses CodeForces - 1000E(缩点 建图 求桥 求直径)

    题意: 就是求桥最多的一条路 解析: 先求连通分量的个数 然后缩点建图  求直径即可 #include <bits/stdc++.h> #define mem(a, b) memset(a ...

  7. [HAOI2010]软件安装(树形背包,tarjan缩点)

    题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是 ...

  8. Codeforces 743D:Chloe and pleasant prizes(树形DP)

    http://codeforces.com/problemset/problem/743/D 题意:求最大两个的不相交子树的点权和,如果没有两个不相交子树,那么输出Impossible. 思路:之前好 ...

  9. HDu 3449 (有依赖的01背包) Consumer

    题意: 有n件物品,对应有不同的价格和价值,这是典型的01背包.但现在有了一个限制,要买物品先买能装这件物品的特定的盒子,盒子的价值为0 代码理解得还不是太好,感觉这是一个“二重”的01背包.首先假设 ...

随机推荐

  1. HTTP协议学习 - 9 Method Definitions

    # 前言 官方文档简略翻译.9 不是代表第九篇,而是在 RFC2616 中是第九篇.重要加粗,龟速翻译. # Method 9.3 GET The GET method means retrieve ...

  2. ASP.NET MVC 学习笔记1 Talk about controller & route

    For the sake of learning programming better, I'd like to increase the frequency of using English. So ...

  3. vs2015 生成 cordova 页面中文乱码

    原文:vs2015 生成 cordova 页面中文乱码 1.用VS2015新创建Cordova项目,启动运行index.html 中文显示乱码 解决方案: 1.使用text/html通用解析编码utf ...

  4. Mono.Cecil - 0.6

    原文:Mono.Cecil - 0.6 项目地址:Mono.Cecil 项目描述:In simple English, with Cecil, you can load existing manage ...

  5. Qt 5.9对Mac的图形显示有许多改进

    We have some platform specific improvements as well as support for new platforms and compilers comin ...

  6. MessageBox用法大全

    //1.显示提示信息 MessageBox.Show("Hello World!"); //2.给消息框加上标题 MessageBox.Show("Hello World ...

  7. 关于powerdesigner中的data types说明

    原文:关于powerdesigner中的data types说明 这一堆的数据类型看着真是头大,弄个表格对照一下. Numeric data types Standard datatype DBMS- ...

  8. 零元学Expression Blend 4 - Chapter 7 什麽?影片不再是印象中的方框框!!!看Blend 4如何把影片镶入字里

    原文:零元学Expression Blend 4 - Chapter 7 什麽?影片不再是印象中的方框框!!!看Blend 4如何把影片镶入字里 本章将教大家如何在Blend 4里新增Media El ...

  9. fatal error LNK1169:找到一个或多个重定义的符号

    这个算是个比较基础的问题,由于我不是C程序员,本行java,临时拉来做的,所以有些坑还得自己走出来. 这个问题是由于,全局变量在a.h中定义,在两个源文件a.cpp和b.cpp中引用,之后被编译器认为 ...

  10. MySQL 常用数据存储引擎区别

    mysql有多种存储引擎,目前常用的是 MyISAM 和 InnoDB 这两个引擎,除了这两个引擎以为还有许多其他引擎,有官方的,也有一些公司自己研发的.这篇文章主要简单概述一下常用常见的 MySQL ...