Codeforces Round #358 (Div. 2)——C. Alyona and the Tree(树的DFS+逆向思维)
2016-06-20 23:23
453 查看
C. Alyona and the Tree
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
Alyona decided to go on a diet and went to the forest to get some apples. There she unexpectedly found a magic rooted tree with root in the vertex 1,
every vertex and every edge of which has a number written on.
The girl noticed that some of the tree's vertices are sad, so she decided to play with them. Let's call vertex v sad if
there is a vertex u in subtree of vertex v such
that dist(v, u) > au,
where au is
the number written on vertex u, dist(v, u) is
the sum of the numbers written on the edges on the path from v to u.
Leaves of a tree are vertices connected to a single vertex by a single edge, but the root of a tree is a leaf if and only if the
tree consists of a single vertex — root.
Thus Alyona decided to remove some of tree leaves until there will be no any sad vertex left in the tree. What is the minimum number of leaves Alyona needs to remove?
Input
In the first line of the input integer n (1 ≤ n ≤ 105)
is given — the number of vertices in the tree.
In the second line the sequence of n integers a1, a2, ..., an (1 ≤ ai ≤ 109)
is given, where ai is
the number written on vertex i.
The next n - 1 lines describe tree edges: ith of
them consists of two integers pi and ci (1 ≤ pi ≤ n, - 109 ≤ ci ≤ 109),
meaning that there is an edge connecting vertices i + 1 and pi with
number ci written
on it.
Output
Print the only integer — the minimum number of leaves Alyona needs to remove such that there will be no any sad vertex left in the tree.
Example
input
output
Note
The following image represents possible process of removing leaves from the tree:
比较有意思的一道题,刚开始题意理解错了,以为一定是从1开始,后来发现是最远可以是1,最近就是从父节点开始,那么边权和就变成了Max{0(舍弃之前的边从最近的父节点开始),sumpre(加上之前的边)}。然后再发现这道题也叫什么树形DP,反正也就听过的样子。一开始写BFS只能过两组数据,因为无法知道到底最合适起点在哪里。因此要用动态的思想,一开是BFS去计算减掉多少枝叶,看了别人博客才明白用逆向思维,因为你减掉的枝叶可能会重复,也可能这个枝叶根本不是从最优开始点开始计算的,也就无法得知这个节点到底算不算sad……题意是若中间出现了一个sad,那么这个sad点的后代点全部都要摘掉,因此去计算从1开始向外拓展的可保留点比较好,那显然就是DFS了。还有由于是无向图,边数要乘以2,两次RE
代码:
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
Alyona decided to go on a diet and went to the forest to get some apples. There she unexpectedly found a magic rooted tree with root in the vertex 1,
every vertex and every edge of which has a number written on.
The girl noticed that some of the tree's vertices are sad, so she decided to play with them. Let's call vertex v sad if
there is a vertex u in subtree of vertex v such
that dist(v, u) > au,
where au is
the number written on vertex u, dist(v, u) is
the sum of the numbers written on the edges on the path from v to u.
Leaves of a tree are vertices connected to a single vertex by a single edge, but the root of a tree is a leaf if and only if the
tree consists of a single vertex — root.
Thus Alyona decided to remove some of tree leaves until there will be no any sad vertex left in the tree. What is the minimum number of leaves Alyona needs to remove?
Input
In the first line of the input integer n (1 ≤ n ≤ 105)
is given — the number of vertices in the tree.
In the second line the sequence of n integers a1, a2, ..., an (1 ≤ ai ≤ 109)
is given, where ai is
the number written on vertex i.
The next n - 1 lines describe tree edges: ith of
them consists of two integers pi and ci (1 ≤ pi ≤ n, - 109 ≤ ci ≤ 109),
meaning that there is an edge connecting vertices i + 1 and pi with
number ci written
on it.
Output
Print the only integer — the minimum number of leaves Alyona needs to remove such that there will be no any sad vertex left in the tree.
Example
input
9 88 22 83 14 95 91 98 53 11 3 24 7 -8 1 67 1 64 9 65 5 12 6 -80 3 8
output
5
Note
The following image represents possible process of removing leaves from the tree:
比较有意思的一道题,刚开始题意理解错了,以为一定是从1开始,后来发现是最远可以是1,最近就是从父节点开始,那么边权和就变成了Max{0(舍弃之前的边从最近的父节点开始),sumpre(加上之前的边)}。然后再发现这道题也叫什么树形DP,反正也就听过的样子。一开始写BFS只能过两组数据,因为无法知道到底最合适起点在哪里。因此要用动态的思想,一开是BFS去计算减掉多少枝叶,看了别人博客才明白用逆向思维,因为你减掉的枝叶可能会重复,也可能这个枝叶根本不是从最优开始点开始计算的,也就无法得知这个节点到底算不算sad……题意是若中间出现了一个sad,那么这个sad点的后代点全部都要摘掉,因此去计算从1开始向外拓展的可保留点比较好,那显然就是DFS了。还有由于是无向图,边数要乘以2,两次RE
代码:
#include<iostream> #include<algorithm> #include<cstdlib> #include<sstream> #include<cstring> #include<cstdio> #include<string> #include<deque> #include<stack> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; #define INF 0x3f3f3f3f #define MM(x) memset(x,0,sizeof(x)) #define MMINF(x) memset(x,INF,sizeof(x)) typedef long long LL; const double PI=acos(-1.0); const int N=200010; int r; struct info { int to; int pre; int d; }E ; int head ,cnt,w ,vis ; void add(int s,int t,int dx) { E[cnt].to=t; E[cnt].pre=head[s]; E[cnt].d=dx; head[s]=cnt++; } void init() { memset(head,-1,sizeof(head)); MM(w);MM(vis); cnt=0; r=0; } void dfs(const int &now,const int &pre,const LL &nowval) { if(w[now]<nowval||vis[now]) return ; vis[now]=1; r++; for (int i=head[now]; i!=-1; i=E[i].pre) { int v=E[i].to; dfs(v,now,max<LL>((LL)0,((LL)nowval+(LL)E[i].d))); } } int main(void) { int n,i,j,x,y; while (~scanf("%d",&n)) { init(); for (i=1; i<=n; i++) { scanf("%d",&w[i]); } for (i=1; i<=n-1; i++) { scanf("%d%d",&x,&y); add(i+1,x,y); add(x,i+1,y); } dfs(1,1,(LL)0); printf("%d\n",n-r); } return 0; }
相关文章推荐
- Win2003利用dfs(分布式文件系统)在负载均衡下的文件同步配置方案
- win2003分布式文件系统(dfs)配置方法[图文详解]
- win2003分布式文件系统及其部署 图文教程
- Hadoop2.6+jdk8的安装部署(1)——使用jar包安装部署【详细】
- Hadoop FS Shell
- DFS使用方法总结
- FastDFS注意事项
- 无忧技术带您预览DFS(分布式文件系统)管理控制台
- C 语言实现迷宫 DFS算法
- 一幅图弄清DFT与DTFT,DFS的关系
- HDFS---Namenode
- HDFS ---- Services startup
- POJ1523 SPF dfs
- Codeforces Round #197 (Div. 2)
- Codeforces Round #198 (Div. 1)
- Codeforces 405E Codeforces Round #238 (Div. 2)E
- Codeforces 407C Codeforces Round #239 (Div. 1)C
- poj1731 Orders dfs
- Surrounded Regions
- Binary Tree Zigzag Level Order Traversal,Restore IP Addresses,Word Search,Simplify Path