题目链接:
明显是一个斜率优化的形式,套一个斜率优化的板子就好了,重点是dfs的时候要记录操作,并且进行还原。
代码:
#include<bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
int tot,head[MAXN],n,p,stk[MAXN],le,ri;
ll dp[MAXN],ans,sum[MAXN];
struct edge
{
int to,nxt,w;
}E[MAXN*2];
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)
{
E[tot].to=v;E[tot].w=w;E[tot].nxt=head[u];
head[u]=tot++;
E[tot].to=u;E[tot].w=w;E[tot].nxt=head[v];
head[v]=tot++;
}
ll getUp(int k,int j)
{
return (dp[k]+1LL*sum[k]*sum[k])-(dp[j]+1LL*sum[j]*sum[j]);
}
ll getDown(int k,int j)
{
return sum[k]-sum[j];
}
void dfs(int now,int f)
{
vector<pair<int,int> > sv;
int l=le,r=ri;
while(le+1<ri&&getUp(stk[le+1],stk[le])<=getDown(stk[le+1],stk[le])*2LL*sum[now])
{
sv.push_back(mp(le,stk[le]));
le++;
}
if(now!=1)
{
dp[now]=dp[stk[le]]+(1LL*sum[now]-sum[stk[le]])*(1LL*sum[now]-sum[stk[le]])+p;
ans=max(ans,dp[now]);
}
while(le+1<ri&&getUp(stk[ri-1],stk[ri-2])*getDown(now,stk[ri-1])>=getUp(now,stk[ri-1])*getDown(stk[ri-1],stk[ri-2]))
{
ri--;
sv.push_back(mp(ri,stk[ri]));
}
stk[ri++]=now;
for(int i=head[now];~i;i=E[i].nxt)
{
int v=E[i].to;
if(v==f)
continue;
sum[v]=sum[now]+E[i].w;
dfs(v,now);
}
le=l,ri=r;
for(int i=0;i<sv.size();i++)
{
int pos=sv[i].xx,id=sv[i].yy;
stk[pos]=id;
}
}
void solve()
{
init();
scanf("%d%d",&n,&p);
for(int i=1;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
}
le=ri=0;
ans=0;
dp[1]=-p;
dfs(1,0);
printf("%lld\n",ans);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}