$n\le 10000$直接莽了一发$O(n^2)$的暴力,然而T掉了.
考虑换根dp.
len[u]表示在u的子树中从u向下的最长链长度,l1[u]表示u的孩子中有最大len[]的点,l2[u]表示u的孩子中次大len[]的点,fw[u]表示u连向其父亲的边权
显然这三条信息可以一遍dfs求出,接下来我们考虑换根dp.
u到其它点的最长距离,要么是u到其子树中某个点的最长距离(也就是$len[u]$),要么是到u的父亲最远的距离(不能在u的子树中)加上$fw[u]$,设为$fal$,dfs的时候向下传递
考虑更新$fal$.设当前正在处理$u$的一个孩子$v$
- 当$v=l1[u]$,即v是u向下的最长链里面的,那我们就只能用次长链,$fal=max(fal+fw[u],len[l2[u]]+fw[l2[u]]+e[i].w)$
- 否则,我们就用最长链,$fal=max(fal+fw[u],len[l1[u]]+fw[l1[u]]+e[i].w)$
时间复杂度为$O(n)$
/**********/省略快读
#define MAXN 10011
struct Edge
{
ll v,w,nxt;
}e[MAXN];
ll cnt=0,last[MAXN];
void adde(ll u,ll v,ll w)
{
++cnt;
e[cnt].v=v;e[cnt].w=w;
e[cnt].nxt=last[u],last[u]=cnt;
}
ll fa[MAXN],fw[MAXN],len[MAXN],l1[MAXN],l2[MAXN],ans[MAXN];
void dfs1(ll u)
{
len[u]=0;
for(ll i=last[u];i;i=e[i].nxt)
{
ll v=e[i].v;
dfs1(v);
if(len[v]+e[i].w>len[l1[u]]+fw[l1[u]])l2[u]=l1[u],l1[u]=v,len[u]=len[v]+e[i].w;
else if(len[v]+e[i].w>len[l2[u]]+fw[l2[u]])l2[u]=v;
}
}
void dfs2(ll u,ll fal=0)
{
ans[u]=max(fal,len[u]);
for(ll i=last[u];i;i=e[i].nxt)
{
ll v=e[i].v;
if(l1[u]==v)
{
dfs2(v,max(fal+fw[u],len[l2[u]]+fw[l2[u]]+e[i].w));
}
else dfs2(v,max(fal+fw[u],len[l1[u]]+fw[l1[u]]+e[i].w));
}
}
int main()
{
ll n;
while(std::cin>>n)
{
memset(last,0,sizeof last);
cnt=0;
memset(ans,0,sizeof ans);
memset(fa,0,sizeof fa);memset(len,0,sizeof len);memset(l1,0,sizeof l1);memset(l2,0,sizeof l2);
for(ll i=2;i<=n;++i)
{
fa[i]=read();
fw[i]=read();
adde(fa[i],i,fw[i]);
}
dfs1(1);
dfs2(1);
for(ll i=1;i<=n;++i)printf("%lld\n",ans[i]);
}
return 0;
}
dfs2中的dfs2(v,max(fal+fw[u],len[l2[u]]+fw[l2[u]]+e[i].w)); fw[u]应该是fw[v]吧.因为要用v替换u做根,所以u,v之间的边才是要加入的.
u,v间的边是
e[i].w
吧e[i].w与fw[v]是等价的
嗯?为什么main函数的dfs2只传了一个数?
哦懂了
我是sb有一个=0啊。