Niuke-árbol blanco y negro (árbol dp)

Enlace de tema

Pregunta:
Inserte la descripción de la imagen aquí
Solución:

Debido a que está coloreando hacia arriba, los nodos de las hojas deben seleccionarse. Entonces hay dos situaciones:
1. ¿Puede el nodo i ser coloreado por un punto en el subárbol, entonces este punto definitivamente será seleccionado?
2. El nodo i puede teñirse con un cierto punto j en el subárbol, entonces hay una pregunta, si elegir el punto i, porque podemos teñir el punto i primero y luego el punto j, ¿cómo tratarlo?
Podemos adjuntar el nodo hijo al nodo padre y luego actualizar la distancia más lejana del nodo padre: k [fa] = max (k [fa], k [hijo] -1). De esta manera, el valor restante de los puntos no utilizados se puede colocar en el nodo ancestro. Si los puntos seleccionados no se pueden teñir en el nodo i, entonces los puntos no seleccionados se pueden usar para teñir. Entonces, ¿cómo ver si el punto seleccionado se puede teñir al punto i? Podemos configurar dp [i] para representar la distancia más lejana que puede extender el punto seleccionado en el subárbol de i. Entonces es dp [u] = max (dp [u], dp [v] -1).

Código:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=1e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
struct node
{
    
    
    int to;
    int next;   
}e[MAXN<<1];
int head[MAXN],k[MAXN];
int cnt=0;
int fa[MAXN];
int ans=0;
int dp[MAXN];
void add(int u,int v)
{
    
    
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void dfs(int u,int f)
{
    
    
    for(int i=head[u];i!=-1;i=e[i].next)
    {
    
    
        int v=e[i].to;
        if(v==f) continue;
        dfs(v,u);
        dp[u]=max(dp[u],dp[v]-1);
    }
    if(!dp[u])
    {
    
    
        ans++;
        dp[u]=k[u];
    }
    else
    {
    
    
        k[fa[u]]=max(k[fa[u]],k[u]-1);
    }
}
int main()
{
    
    
    int n;
    memset(head,-1,sizeof head);
    cin>>n;
    fa[1]=0;
    for(int i=2;i<=n;i++)
    {
    
    
        int x;
        cin>>x;
        add(x,i);
        add(i,x);
        fa[i]=x;
    }
    for(int i=1;i<=n;i++)
    {
    
    
        cin>>k[i];
    }
    dfs(1,0);
    printf("%d\n",ans);
}

Supongo que te gusta

Origin blog.csdn.net/weixin_45755679/article/details/113747997
Recomendado
Clasificación