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);
    }
  • 相关阅读:
    arm-linux-gcc-4.5.1的安装…
    OK6410之tftp下载内核,nfs…
    非常详细的ok6410的linux系统移植…
    2009-2010网络最热的&nbsp;嵌入式…
    Vue-基础(二)
    【SpringBoot】Springboot1.5.9整合WebSocket
    Hadoop本地环境安装
    Vue-基础(一)
    【Jwt】JSON Web Token
    【JDK8】Java8 新增BASE64加解密API
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14605899.html
Copyright © 2011-2022 走看看