题解 P6722 【「MCOI-01」Village 村庄】

· · 题解

看到大家方法都不同。

此处献上换根dp

记一下每个点子树离他最远的三个点的距离 记一下每个点父亲最远距离 然后判断一下>=k就行

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
const int maxn=200010;
struct edge{
    int next,to,w;
}a[maxn*2];
int head[maxn],len;
void add(int x,int y,int z){
    a[++len]={head[x],y,z};
    head[x]=len;
}
int i,j,k,n,m,dp[maxn][4];//dp[][0]=每个点父亲最远距离,dp[][1]/[2]/[3]=每个点子树离他最远的三个点的距离。
void dfs(int now,int fa){
    for(int i=head[now];i;i=a[i].next){
        int u=a[i].to;
        if(u==fa)continue;
        dfs(u,now);
        if(dp[u][0]+a[i].w>dp[now][0]){//记录一下
            dp[now][3]=dp[now][2];
            dp[now][2]=dp[now][0];
            dp[now][0]=dp[u][0]+a[i].w;
            dp[now][1]=u;
        }else
        if(dp[u][0]+a[i].w>dp[now][2]){
            dp[now][3]=dp[now][2];
            dp[now][2]=dp[u][0]+a[i].w;
        }else
        if(dp[u][0]+a[i].w>dp[now][3])
            dp[now][3]=dp[u][0]+a[i].w;
    }
}
bool B=true;
void dfs2(int now,int fa,int len){
    for(int i=head[now];i;i=a[i].next){
        int u=a[i].to;
        if(u==fa)continue;
        if(u==dp[now][1])dfs2(u,now,max(len,dp[now][2])+a[i].w);
        else dfs2(u,now,max(len,max(len,dp[now][0])+a[i].w));
    }
    if((len>=k) + (dp[now][0]>=k) + (dp[now][2]>=k)>=2)B=false;//判断
    if(len+dp[now][2]>=k && dp[now][0]+dp[now][2]>=k)B=false;
    if(dp[now][2]+dp[now][3]>=k)B=false;
}
int main(){
    int T;cin>>T;
    while(T--){
        B=true;
        n=read();k=read();
        for(i=1;i<n;i++){
            int x=read(),y=read(),z=read();
            add(x,y,z);add(y,x,z);//加边
        }
        dfs(1,0);dfs2(1,0,0);
        if(B)puts("Yes");
        else puts("Baka Chino");
        for(i=1;i<=n;i++)dp[i][0]=dp[i][1]=dp[i][2]=dp[i][3]=head[i]=0;len=0;//赋初始值
    }
    return 0;
}