fogflea
fogflea
发布于 2025-10-18 / 3 阅读
0
0

CF1442E Black, White and Grey Tree

首先有一个基本的简化,因为是删一个连通块,所以一个极大的连通块一定会被一起删,所以可以缩成一个点。

然后接下来就是一些手法了,弱化问题,只考虑黑白点,那么经过刚才的操作,树上的同色点一定不相邻,那么很自然的就能想到操作数和直径相关,加上灰点后,实际等价于染白或黑,那么 \texttt{dp} 即可。

#include<bits/stdc++.h>
using namespace std;
#define fio(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
#define tio() freopen("in.txt","r",stdin),freopen("out.txt","w",stdout)
using ll=long long;
int T;
int n;
const int N=2e5+10,inf=0x3f3f3f;
int a[N];
vector<int>g[N];
void addedge(int u,int v){
    g[u].push_back(v);
    g[v].push_back(u);
}
int f[N][2],h[N][2];
void pre(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        f[i][0]=f[i][1]=1;
        h[i][0]=h[i][1]=1;
        a[i]=(a[i]+2)%3;
        g[i].clear();
        if(a[i]==2)continue;
        f[i][a[i]^1]=inf;
        h[i][a[i]^1]=inf;
    }
    for(int i=1;i<n;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        addedge(u,v);
    }
}
void dfs(int u,int fa){
    for(int v:g[u]){
        if(v==fa)continue;
        dfs(v,u);
    }
    for(int i=0;i<=1;++i){
        int mx=0,mx2=0;
        for(int v:g[u]){
            if(v==fa)continue;
            f[u][i]=max(f[u][i],min(f[v][0],f[v][1]));
            if(min(h[v][i],h[v][i^1]+1)>mx){
                mx2=mx;
                mx=min(h[v][i],h[v][i^1]+1);
            }
            else if(min(h[v][i],h[v][i^1]+1)>mx2)
                mx2=min(h[v][i],h[v][i^1]+1);
        }
        h[u][i]=max(h[u][i],mx);
        f[u][i]=max(f[u][i],mx+mx2-(mx&&mx2));
    }
}
void work(){
    dfs(1,0);
    printf("%d\n",min(f[1][0],f[1][1])/2+1);
}
int main(){
    scanf("%d",&T);
    while(T--){
        pre();
        work();
    }  
    return 0;
}

评论