Codeforces 682C Alyona and the Tree (树上DFS+DP)

题目链接:http://codeforces.com/problemset/problem/682/C

题目大意:
取树上任意一个点v,若点v的子树中有一个点u使得dist(v,u)>a[u]那么称节点v是伤心的。
给你一个根为1的树,每个节点有一个权值a[i],每条边也有一个权值w,
现在让你删最少的结点,使得树上不存在伤心的点。
解题思路:
删除最少的点,我们可以反一下,变成找最多的点,使得这些点不伤心。
只要对这棵树进行DFS,同时记录路径长度dis,当到达某点u时,
若dis>a[u],那么要将u及u的子树删除,所以直接return,不再继续遍历。
注意,这里的dis是1~u的最长路径,所以当dis<0时使得dis=0,类似最大子段和的做法。

代码:

 1 #include<bits/stdc++.h>
 2 #define lc(a) (a<<1)
 3 #define rc(a) (a<<1|1)
 4 #define MID(a,b) ((a+b)>>1)
 5 #define fin(name)  freopen(name,"r",stdin)
 6 #define fout(name) freopen(name,"w",stdout)
 7 #define clr(arr,val) memset(arr,val,sizeof(arr))
 8 #define _for(i,start,end) for(int i=start;i<=end;i++)
 9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
10 using namespace std;
11 typedef long long LL;
12 const int N=2e5+5;
13 const int INF=0x3f3f3f3f;
14 const double eps=1e-10;
15 
16 struct node{
17     int to,w;
18     node(int to,int w):to(to),w(w){}
19 };
20 
21 int ans;
22 int a[N];
23 vector<node>v[N];
24 
25 void dfs(int u,LL dis,int fa){
26     if(dis>a[u]) return;    //dis(v,u)>a[u]不符合 
27     ans++;
28     for(int i=0;i<v[u].size();i++){
29         node t=v[u][i];
30         if(t.to==fa) continue;
31         dfs(t.to,max(0LL,dis+t.w),u);//dis<0则取0 
32     }
33 }
34 
35 int main(){
36     FAST_IO;
37     int n;
38     cin>>n;
39     for(int i=1;i<=n;i++){
40         cin>>a[i];
41     }
42     for(int i=2;i<=n;i++){
43         int to,w;
44         cin>>to>>w;
45         v[i].push_back(node(to,w));
46         v[to].push_back(node(i,w));
47     }
48     dfs(1,0,-1);
49     cout<<n-ans<<endl;
50     return 0;
51 }

猜你喜欢

转载自www.cnblogs.com/fu3638/p/9131474.html