HDU 2196 Computer

mac2024-05-12  32

题目大意

%   给定一棵边带权树,你需要输出对于每个点而言,距离它最远的点和它的距离。   数据范围  1 ⩽ n ⩽ 1 0 4 , 1 ⩽ w ( u , v ) ⩽ 1 0 9 1\leqslant n\leqslant 10^4,1\leqslant w_{(u,v)}\leqslant 10^9 1n104,1w(u,v)109

题解

%   无根树不好考虑,先钦定一个点为根节点。 %   考虑树形dp,定义 d o w n [ u ] down[u] down[u] 表示点 u u u 的子树中距离点 u u u 最远的点到点 u u u 的距离。则有 d o w n [ u ] = max ⁡ v ∈ s o n ( u ) { d o w n [ v ] + 1 } down[u]=\max_{v\in son(u)}\{down[v]+1\} down[u]=vson(u)max{down[v]+1}

%   求出后,我们考虑求出子树外的答案,定义 u p [ u ] up[u] up[u] 表示不考虑 u u u 点的子树,其余点到点 u u u 的最远的点到点 u u u 的距离,由于已经求出了 d o w n down down,这里的转移也不难。 u p [ u ] = max ⁡ { u p [ f a ( u ) ] + w ( u , f a ( u ) ) max ⁡ t ∈ s o n ( f a ( u ) ) , t ≠ u d o w n [ t ] + w ( t , f a ( u ) ) + w ( f a ( u ) , u ) up[u]=\max\begin{cases}up[fa(u)]+w_{(u,fa(u))}\\\max\limits_{t \in son(fa(u)),t\not=u}down[t]+w_{(t,fa(u))}+w_{(fa(u),u)}\end{cases} up[u]=maxup[fa(u)]+w(u,fa(u))tson(fa(u)),t=umaxdown[t]+w(t,fa(u))+w(fa(u),u)

%   上面那条是通过父亲直接转移,下面那条通过其他儿子通过父亲连到自己的。   考虑如何线性求出下面哪条式子的值。若我们假设 f a ( u ) fa(u) fa(u) 的第 k k k 个儿子为 s o n ( f a ( u ) ) [ k ] son(fa(u))[k] son(fa(u))[k],则定义 p r e [ k ] = max ⁡ p = 1 k w ( s o n ( f a ( u ) [ p ] , f a ( u ) ) ) + d o w n [ s o n ( f a ( u ) ) [ p ] ] , f i x [ k ] = max ⁡ p = k ∣ s o n ( f a ( u ) ) ∣ w ( s o n ( f a ( u ) [ p ] , f a ( u ) ) ) + d o w n [ s o n ( f a ( u ) ) [ p ] ] pre[k]=\max_{p=1}^{k} w_{(son(fa(u)[p],fa(u)))}+down[son(fa(u))[p]],\\fix[k]=\max_{p=k}^{|son(fa(u))|} w_{(son(fa(u)[p],fa(u)))}+down[son(fa(u))[p]] pre[k]=p=1maxkw(son(fa(u)[p],fa(u)))+down[son(fa(u))[p]],fix[k]=p=kmaxson(fa(u))w(son(fa(u)[p],fa(u)))+down[son(fa(u))[p]]

%   若 u u u f a ( u ) fa(u) fa(u) 的第 s s s 个儿子,则转移可以写成 u p [ u ] = max ⁡ { u p [ f a ( u ) ] + w ( u , f a ( u ) ) s u f [ s − 1 ] + f i x [ s + 1 ] + w ( f a ( u ) , u ) up[u]=\max\begin{cases}up[fa(u)]+w_{(u,fa(u))}\\suf[s-1]+fix[s+1]+w_{(fa(u),u)}\end{cases} up[u]=max{up[fa(u)]+w(u,fa(u))suf[s1]+fix[s+1]+w(fa(u),u)

%   如此,我们考虑在访问 f a ( u ) fa(u) fa(u) 时,将 f a ( u ) fa(u) fa(u) 的每个儿子都算出来,如此递推,最后的答案便是 max ⁡ ( u p [ u ] , d o w n [ u ] ) \max(up[u],down[u]) max(up[u],down[u])。详见代码(变量和上述定义基本一致)。时间复杂度 Θ ( n ) \Theta(n) Θ(n)

代码

#include<bits/stdc++.h> using namespace std; #define int long long #define maxn 10010 struct edge{ int v,w,next; }edges[maxn<<1]; int n,head[maxn],cnt=0; void ins(int u,int v,int w){ edges[++cnt]=(edge){v,w,head[u]}; head[u]=cnt; } int down[maxn]; void dfs(int u,int fa=-1){ down[u]=0; for(int i=head[u];i;i=edges[i].next){ int v=edges[i].v; if(v==fa) continue; dfs(v,u); down[u]=max(down[u],down[v]+edges[i].w); } } int up[maxn],pre[maxn],suf[maxn],fix[maxn],son[maxn],wei[maxn]; void redfs(int u,int fa=-1){ int cnt=0; for(int i=head[u];i;i=edges[i].next){ int v=edges[i].v; if(v==fa) continue; up[v]=max(up[v],up[u]+edges[i].w); son[++cnt]=v; wei[cnt]=edges[i].w; pre[cnt]=max(pre[cnt-1],down[v]+edges[i].w); } fix[cnt+1]=0; for(int i=cnt;i>0;i--) fix[i]=max(fix[i+1],down[son[i]]+wei[i]); for(int i=1;i<=cnt;i++) up[son[i]]=max(up[son[i]],wei[i]+max(pre[i-1],fix[i+1])); for(int i=head[u];i;i=edges[i].next){ int v=edges[i].v; if(v==fa) continue; redfs(v,u); } } signed main(){ while(~scanf("%lld",&n)){ memset(down,0,sizeof down); memset(pre,0,sizeof pre); memset(suf,0,sizeof suf); memset(fix,0,sizeof fix); memset(head,cnt=0,sizeof head); memset(up,0,sizeof up); for(int i=2,v,w;i<=n;i++){ scanf("%lld%lld",&v,&w); ins(i,v,w);ins(v,i,w); } dfs(1); redfs(1); for(int i=1;i<=n;i++) printf("%lld\n",max(up[i],down[i])); } return 0; }
最新回复(0)