• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
dwtfukgv
博客园    首页    新随笔    联系   管理    订阅  订阅
CodeForces 682C Alyona and the Tree (树上DFS)

题意:给定一棵树,每个叶子有一个权值,每条边也有一个权值,现在让你删最少的结点,使得从任何结点出发到另一个结点的边上权值和都小于两个结点的权值。

析:很明显是DFS,不过要想找出最少的结点可能不太容易,所以我们可以先找出剩下结点最多,那么用总数减去这个就好,那么怎么找哪些结点是剩下的呢?首先要知道,如果一个结点要被删掉,

那么它的子树肯定也要被删掉,并且,要满足dist(v, u) <= a[u]才是可能留下的,那么只要dist(v, u) >a[u],就不要,所以一定要注意的是,结点的距离可能为负,所以要在DFS时判断一下,肯定是取非负的,

想一想为什么。

代码如下:

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5 + 5;
typedef long long LL;
typedef pair<int, int> P;
int a[maxn];
vector<P> G[maxn];
int ans;

void dfs(int u, LL d, int fa){
    if(a[u] < d)  return ;//不满足要删掉
    ++ans;//计算最多有多少结点
    for(int i = 0; i < G[u].size(); ++i)
        if(G[u][i].first == fa)  continue;//不能返回父结点
        else   dfs(G[u][i].first, max(0LL, d+G[u][i].second), u);//判断是不是大于等于0
}

int main(){
    int n, p, c;
    cin >> n;
    for(int i = 1; i <= n; ++i) cin >> a[i];
    for(int i = 1; i < n; ++i){
        cin >> p >> c;
        G[i+1].push_back(P(p, c));
        G[p].push_back(P(i+1, c));
    }
    ans = 0;
    dfs(1, 0, -1);
    printf("%d\n", n - ans);
    return 0;
}

 

posted on 2016-07-09 14:58  dwtfukgv  阅读(409)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3