zoukankan      html  css  js  c++  java
  • Nowcoder13249.黑白树(树形DP)

    一棵n个点的有根树,1号点为根,相邻的两个节点之间的距离为1。树上每个节点i对应一个值k[i]。每个点都有一个颜色,初始的时候所有点都是白色的。
    你需要通过一系列操作使得最终每个点变成黑色。每次操作需要选择一个节点i,i必须是白色的,然后i到根的链上(包括节点i与根)所有与节点i距离小于k[i]的点都会变黑,已经是黑的点保持为黑。问最少使用几次操作能把整棵树变黑。

    //先记一遍每个子树的最大向上高度
    //然后对每个叶子节点染色 
    //遇到没染色的节点,去子树里找最大的高度,更新高度
    
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    int n,k[maxn];
    vector<int> g[maxn];
    int dep[maxn];
    int ans;
    int h[maxn];//h_x表示x子树内可以往上走的最高高度
    int f[maxn];//f_x表示x子树内当前往上走的最高高度 
    void dfs (int x,int pre) {
    	dep[x]=dep[pre]+1;
    	h[x]=dep[x]-k[x]+1; 
    	for (int y:g[x]) {
    		if (y==pre) continue;
    		dfs(y,x);
    		h[x]=min(h[x],h[y]);
    	}
    }
    void dfs1 (int x,int pre) {
    	dep[x]=dep[pre]+1;
    	int Min=1e9;
    	for (int y:g[x]) {
    		if (y==pre) continue;
    		dfs1(y,x);
    		Min=min(Min,f[y]);
    	}
    	if (Min<=dep[x]) {
    		f[x]=Min;
    	}
    	else {
    		f[x]=h[x];
    		ans++;
    	}
    }
    int main () {
    	scanf("%d",&n);
    	for (int i=2;i<=n;i++) {
    		int x;
    		scanf("%d",&x);
    		g[x].push_back(i);
    	} 
    	for (int i=1;i<=n;i++) scanf("%d",k+i),f[i]=1e9;
    	dfs(1,0);
    	dfs1(1,0);
    	printf("%d
    ",ans);
    }
  • 相关阅读:
    LeetCode 275. H-Index II
    LeetCode 274. H-Index
    LeetCode Gray Code
    LeetCode 260. Single Number III
    LeetCode Word Pattern
    LeetCode Nim Game
    LeetCode 128. Longest Consecutive Sequence
    LeetCode 208. Implement Trie (Prefix Tree)
    LeetCode 130. Surrounded Regions
    LeetCode 200. Number of Islands
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14605899.html
Copyright © 2011-2022 走看看