Tree

题目链接:http://10.160.111.129/p/2646

题意:

定义一棵树的cost为根节点到其子树任一节点的长度的最大值(再乘以一个系数k)

每次可以花费c的代价将根转移到其相邻节点

求转移根节点过程中Max(cost-c)

思路:

换根dp

对于一个节点我们很容易求得其为根节点时的子树最长链和次长链

其为根节点时到子树节点的最长长度可以由 原子树最长链(视为下面) 和 其父节点(消除掉该节点后)的最长链(视为上面)取max转移得到

其实最重要的是怎么将该节点对于其父节点的影响消除掉

发现当该节点 下面的最长链+1 等于 上面的最长链 时,说明消除影响后 上面的最长链 为 原次长链

维护每个节点的up值

if(u!=1){
        if(res[fa]==res[u]+1){
            up[u]=max(res2[fa],up[fa])+1;
        }else{
            up[u]=max(res[fa],up[fa])+1;
        }
        ans=max(ans,max(up[u],res[u])*k-t*c);
    }

注意的是父节点的最长链可能是到其子树节点,也有可能是通过它的父节点的最长链转移得到

vector<int>e[maxn];
int ans=-llmax;
int res[maxn];
int res2[maxn];
int up[maxn];
int n,k,c;
void dfs(int u,int fa,int t){
    for(int v:e[u]){
        if(v==fa)continue;
        dfs(v,u,t+1);
        if(res[u]<res[v]+1){
            res2[u]=res[u];
            res[u]=res[v]+1;
        }else if(res2[u]<res[v]+1){
            res2[u]=res[v]+1;
        }
    }
}

void dfs2(int u,int fa,int t){
    if(u!=1){
        up[u]=(res[fa]==res[u]+1)?res2[fa]+1:res[fa]+1;
        ans=max(ans,max(up[u],res[u])*k-t*c);
    }
    for(int v:e[u]){
        if(v==fa)continue;
        dfs2(v,u,t+1);
    }
}
void solve(){
    cin>>n>>k>>c;
    memset(res,0,sizeof res);
    memset(res2,0,sizeof res2);
    memset(up,0,sizeof up);
    rep(i,1,2e5){
        e[i].clear();
    }

    ans=-llmax;
    rep(i,1,n-1){
        int u,v;cin>>u>>v;
        e[u].pb(v);e[v].pb(u);
    }
    dfs(1,0,0);
    ans=max(ans,k*res[1]);
    dfs2(1,0,0);
    cout<<ans<<endl;
}

posted @ 2025-05-14 22:10  Marinaco  阅读(20)  评论(0)    收藏  举报
//雪花飘落效果