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;
}

浙公网安备 33010602011771号