ACM之路(13)—— 树型dp
最近刷了一套(5题)的树型dp题目:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=116767#overview,算是入了个门,做下总结。
A题是真正的入门题,只要找出所有的入度为0的点(即每棵树上最高的领导)进行树型dp即可,具体方法同B题,等到了B题再具体讲。
C题是给出一棵树,升序输出这棵树上所有满足条件的点,该条件是,去掉该节点以后剩下的所有子树的size不超过原数size的一半。方法是以节点1为头,预处理出所有节点的size,然后用dfs遍历所有的点,找出符合条件的点即可。
D题是,给出一个树(树上每个节点都有一个权值)和一个指定的size,找出满足这个size的所有子树中权值最大的一颗子树的权值。因为节点数最大为100,所以只要暴力dp即可。
虽然CD两题都不是很难,但还是需要注意一下写法的。
重点讲下B和E两题。题意都差不多,给出一棵树,B题是每个点都可以覆盖其相邻的一条边,求覆盖所有边所需最少的点的个数。而E题是,每个点都可以覆盖自己和相邻的节点,求覆盖所有点所需的最少的点的个数。
一开始并没有觉得有什么区别,因为都是无环的树,应该B题的方法适用于E,不过最后还是找出了反例。
如上图,如果是覆盖所有点,那么只要2,5两个点即可,如果是覆盖边,那么3,4之间的边仍未覆盖,所以有不同,需要采取新的dp方法。
对于B题,考虑如果u点不设置点,那么即dp[u][0]=dp[v][1],即其子节点一定要放一个点(1表示放,0表示不放);否则,如果u点放置,则dp[u][1]=min(dp[v][0],dp[v][1])。然后用dfs遍历即可。代码如下:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std;
const int N = ;
int dp[N+][];
vector<int> vec[N+];
void dfs(int u,int f)
{
dp[u][]=;
dp[u][]=;
for(int i=;i<vec[u].size();i++)
{
int v=vec[u][i];
if(f==v) continue;
dfs(v,u);
dp[u][]+=dp[v][];
dp[u][]+=min(dp[v][],dp[v][]);
}
}
int main()
{
int n;
while(scanf("%d",&n)==)
{
memset(dp,,sizeof(dp));
for(int i=;i<=N;i++) vec[i].clear();
for(int i=;i<=n;i++)
{
int u,T;
scanf("%d:(%d)",&u,&T);
while(T--)
{
int v;
scanf("%d",&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
}
dfs(,-);
int ans = min(dp[][],dp[][]);
printf("%d\n",ans);
}
return ;
}
对于D题,贪心策略是如果子节点建了,父节点不建;父节点建了,子节点不建。具体的还是见代码理解一下吧:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std; vector<int> G[+];
int build[+];
int ans = ;
void dfs(int u,int from)
{
int f = ; //f=1表示所有子代中具有一个已经放置了点
for(int i=;i<G[u].size();i++)
{
int &v = G[u][i];
if(v == from) continue;
dfs(v,u);
f = f||build[v];
}
if(from == -) ans += (f==&&build[u]==);
else if(build[from] == && build[u] == && f == )
{
ans++;
build[from] = ; //这是贪心策略的体现,可以手动画图模拟一下
}
}
int main()
{
int n;
while(scanf("%d",&n)==)
{
for(int i=;i<=n;i++) G[i].clear();
memset(build,,sizeof(build));
for(int i=;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
ans = ;
dfs(,-);
printf("%d\n",ans);
}
}
模拟过程大致如下:
由于贪心策略,最后三个节点不涂,倒数第二个涂色,那么3自然不用涂,回溯到2节点的时候,由于1,2,3都没涂,而3是有三个儿子节点可以覆盖它的,故不用管,所以涂1即可,这就是代码中,连续3个没涂的情况下涂最前面那个(也就是from)的缘故。同时这也是和B题不同的一个反例。因为2,3之间的边没被覆盖。

ACM之路(13)—— 树型dp的更多相关文章
- HDU_1561_The more, The Better_树型dp
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 The more, The Better Time Limit: 6000/2000 MS (J ...
- HDU_1011_Starship Troopers_树型dp
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1011 Starship Troopers Time Limit: 10000/5000 MS (Jav ...
- HDU_1520_Anniversary party_树型dp
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 Anniversary party Time Limit: 2000/1000 MS (Java ...
- 【题解】Luogu p3047 [USACO12FEB]附近的牛Nearby Cows 树型dp
题目描述 Farmer John has noticed that his cows often move between nearby fields. Taking this into accoun ...
- 【题解】Luogu p2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat 树型dp
题目描述 Bessie is planning the annual Great Cow Gathering for cows all across the country and, of cours ...
- 【题解】Luogu p2014 选课 树型dp
题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一 ...
- POJ3659 Cell Phone Network(树上最小支配集:树型DP)
题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...
- POJ 3342 - Party at Hali-Bula 树型DP+最优解唯一性判断
好久没写树型dp了...以前都是先找到叶子节点.用队列维护来做的...这次学着vector动态数组+DFS回朔的方法..感觉思路更加的清晰... 关于题目的第一问...能邀请到的最多人数..so ea ...
- 【XSY1905】【XSY2761】新访问计划 二分 树型DP
题目描述 给你一棵树,你要从\(1\)号点出发,经过这棵树的每条边至少一次,最后回到\(1\)号点,经过一条边要花费\(w_i\)的时间. 你还可以乘车,从一个点取另一个点,需要花费\(c\)的时间. ...
随机推荐
- C#进阶之WebAPI(三)
今天复习一下WebAPI的路由知识: 首先分析一下MVC路由和WebAPI路由的区别: 在mvc里,默认的路由机制是通过URL路径去匹配控制器和Action方法的,在mvc中的默认路由定义在App_S ...
- Matlab函数kmeans
Matlab函数kmeans K-means聚类算法采用的是将N*P的矩阵X划分为K个类,使得类内对象之间的距离最大,而类之间的距离最小. 使用方法:Idx=Kmeans(X,K)[Idx,C]=Km ...
- Fiddler 基础
Fiddler 基础 来源 https://blog.csdn.net/ohmygirl/article/details/17855031 1.为什么是Fiddler? 抓包工具有很多,小到最常用的w ...
- Spark面试知识点-SparkSQL(1)
0.介绍: (1)Spark SQL的前身是Shark,即Hive on Spark, 1.SparkSQL特点: (1)支持多种数据源:Hive,RDD,Parquet,JSON,JDBC等. (2 ...
- element-ui表格带复选框使用方法及默认选中方法
一.实现多选:步骤1:在表格中添加一列 步骤2:在data中定义以及数组用来存储选中的元素.例如:multipleSelection:[] selection-change方法用户实时监听选中元素 实 ...
- vue中的绑定class和微信小程序中的绑定class的区别
微信小程序 小程序里面的class与style绑定,遵循HTML特性绑定,有关于HTML绑定.在进行class与style绑定时,可以直接绑定,也可以带上逻辑与,或者三元运算进行条件控制 JS dat ...
- nodejs request module里的json参数的一个坑
今天工作的时候遇到一个坑,在客户端用nodejs给服务器发送HTTP请求,服务器老是报错:In the context of Data Services an unknown internal ser ...
- 【github】github的使用
一.上传本地代码 1.在github上新建一个repository(命名为英文) 2.打开cmd,进入上传代码所在目录 3.输入如下命令 第一步:git init --建仓第二步:git add * ...
- 【loj#6220】sum
题目传送门:https://loj.ac/problem/6220 题意:对于一个序列$a$,找出它的一个子序列$b$,使$\sum_{a_i \in b}a_i \equiv 0 \pmod n$ ...
- OpenCV视觉处理核心课程
OpenCV视觉处理核心课程 观看链接:https://www.bilibili.com/video/av29500928?from=search&seid=47008639320014639 ...