题目描述 小C上周末和他可爱的同学小A一起去X湖玩。
X湖景区一共有n个景点,这些景点由n-1条观光道连接着,从每个景点开始都可以通过观光道直接或间接地走到其他所有的景点。小C带着小A从1号景点开始游玩。游览完第一个景点后,先由小C决定下一个游览的景点,他们一起走去那个景点玩。接下来,他们轮流决定他们下一步去哪个景点玩。他们不会选择已经走过的景点,因为重复游览一个景点是无趣的。当他们无法选择下一个景点时,他们就结束旅程。
小C是好动的男孩纸,所以他希望游览的过程尽量长,也就是走过观光道的长度和最大。而小A是文静的女孩纸,她希望游览的过程尽量短。小A和小C都极度聪明,且他们的目光都足够长远,他们做出的决策都是对自己最优的。由于小C在旅游前就仔细研究了X湖景区的地图,他可以在旅行开始前就用自己惊人的数学能力推算出他和小A旅行的路径长度。
小C的梦境是美好的。在他的梦里,他和小A又进行了n-1次旅行,第i次旅行从i+1号点开始,每次也是小C先决定下一个景点,然后小A,然后小C……直到旅行结束。现在小C希望你对于所有n次旅行,求出他和小A旅行的路径长度。 输入 第一行一个正整数n,表示景点的个数。 接下来n-1行,每行三个正整数u,v,c。表示有一条连接u和v的双向观光道,其长度为c。 输出
输出一共N行,每行一个正整数。第i行表示从i号点开始旅行他们走过的路径长度。样例输入
5
1 2 1
1 3 2
2 4 3
2 5 4
样例输出
4
4
7
6
7
提示
从1号景点开始:若小C选择走到3号景点,则小A无法选择下一个景点,旅行的路径长度为2
若小C选择走到2号景点,则小A会在4号景点和5号景点中选择更近的4号点,然后小C无法选择下一个景点,旅行结束,旅行的路径长度会是4
所以小C会选择走到2号点,最终的路径长度是4
【数据范围】
对于20%的数据,N ≤ 15
对于60%的数据,N ≤ 3000
对于100%的数据,N ≤ 300000, c[i] ≤ 1e9
设gmax[u]表示小A从u向下走获得的最大价值。
设gmin[u]表示小C从u向下走获得的最小价值。
gmax[u]:=max{gmin[v]+len[i]};
gmin[u]:=min{gmax[v]+len[i]};
在考虑根节点转移,设fmax[u],f[min] 表示向上走向下走最大最小值,转移同理,详见代码。
代码(c++)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define mod 1000000007
#define N 300005
typedef long long ll;
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const long long inf=300000000000000;
int Head[N],ret[2*N],Next[2*N],len[2*N];
ll gmin[N],gmax[N],Fmin[N],Fmax[N],ans[N];
ll st[N],lmin[N],lmax[N],rmin[N],rmax[N],tmin[N],tmax[N];
int tot,top,n;
void ins(int u,int v,int l)
{
ret[++tot]=v;len[tot]=l;
Next[tot]=Head[u];Head[u]=tot;
}
void dfs(int u,int fa)
{
gmin[u]=inf;
for (int i=Head[u];i;i=Next[i])
{
if (ret[i]==fa) continue;
int v=ret[i];
dfs(v,u);
gmax[u]=max(gmin[v]+len[i],gmax[u]);
gmin[u]=min(gmax[v]+len[i],gmin[u]);
}
if (gmin[u]==inf) gmin[u]=0;
}
void dp(int u,int fa,int dis)
{
int l=top+1;
for (int i=Head[u];i;i=Next[i])
{
if (ret[i]==fa) continue;
int v=ret[i];
tmax[++top]=gmax[v]+len[i];
tmin[top]=gmin[v]+len[i];
}
int r=top;if (r<l) return;
lmin[l]=tmax[l];lmax[l]=tmin[l];
for (int i=l+1;i<=r;i++)
{
lmin[i]=min(tmax[i],lmin[i-1]);
lmax[i]=max(tmin[i],lmax[i-1]);
}
rmin[r]=tmax[r];rmax[r]=tmin[r];
for (int i=r-1;i>=l;i--)
{
rmin[i]=min(tmax[i],rmin[i+1]);
rmax[i]=max(tmin[i],rmax[i+1]);
}
int cnt=l;
for (int i=Head[u];i;i=Next[i])
{
if (ret[i]==fa) continue;
int v=ret[i];
Fmax[u]=Fmin[fa]+dis;
if (cnt!=l) Fmax[u]=max(Fmax[u],lmax[cnt-1]);
if (cnt!=r) Fmax[u]=max(Fmax[u],rmax[cnt+1]);
Fmin[u]=Fmax[fa]+dis;
if (cnt!=l) Fmin[u]=min(Fmin[u],lmin[cnt-1]);
if (cnt!=r) Fmin[u]=min(Fmin[u],rmin[cnt+1]);
ans[v]=max(Fmin[u]+len[i],gmax[v]);
dp(v,u,len[i]);
cnt++;
}
}
int main()
{
n=read();
for (int i=1;i<n;i++)
{
int u=read(),v=read(),l=read();
ins(u,v,l);ins(v,u,l);
}
dfs(1,0);ans[1]=gmax[1];Fmin[0]=-inf;Fmax[0]=inf;
dp(1,0,0);
for (int i=1;i<=n;i++) printf("%lld\n",ans[i]);
return 0;
}
代码(pascal)
var
tot,i,n,u,v,l:longint;
ans,gmax,gmin,pmax,pmin:array[0..300033] of int64;
head:array[0..300033] of longint;
ret,next,len:array[0..600006] of longint;
fmax,fmaxp,fmin,fminp:array[-1..300033,1..2] of int64;
procedure ins(u,v,l:longint);
begin
tot:=tot+1;
ret[tot]:=v;
len[tot]:=l;
next[tot]:=head[u];
head[u]:=tot;
end;
procedure dfs(u,pre:longint);
var
i,v:longint;
flag:boolean;
begin
i:=head[u];
flag:=false;
while i<>0 do
begin
v:=ret[i];
if v<>pre then
begin
flag:=true;
dfs(v,u);
if gmin[v]+len[i]>gmax[u] then
begin
gmax[u]:=gmin[v]+len[i];
pmax[u]:=v;
end;
if gmax[v]+len[i]<gmin[u] then
begin
gmin[u]:=gmax[v]+len[i];
pmin[u]:=v;
end;
end;
i:=next[i];
end;
if flag=false then begin gmax[u]:=0; gmin[u]:=0; end;
end;
procedure find(u,pre,l:longint);
var
i,v:longint;
flag:boolean;
begin
i:=head[u];
if fminp[pre,1]<>u then
begin
fmax[u,1]:=fmin[pre,1]+l;
fmaxp[u,1]:=pre;
end
else
begin
fmax[u,1]:=fmin[pre,2]+l;
fmaxp[u,1]:=pre;
end;
if fmaxp[pre,1]<>u then
begin
fmin[u,1]:=fmax[pre,1]+l;
fminp[u,1]:=pre;
end
else
begin
fmin[u,1]:=fmax[pre,2]+l;
fminp[u,1]:=pre;
end;
if pre=-1 then ans[u]:=0
else if fminp[pre,1]<>u then ans[u]:=fmin[pre,1]+l
else ans[u]:=fmin[pre,2]+l;
while i<>0 do
begin
v:=ret[i];
if v<>pre then
begin
if gmin[v]+len[i]>ans[u] then ans[u]:=gmin[v]+len[i];
if gmin[v]+len[i]>fmax[u,1] then
begin
fmax[u,2]:=fmax[u,1];
fmaxp[u,2]:=fmax[u,1];
fmax[u,1]:=gmin[v]+len[i];
fmaxp[u,1]:=v;
end
else
if gmin[v]+len[i]>fmax[u,2] then
begin
fmax[u,2]:=gmin[v]+len[i];
fmaxp[u,2]:=v;
end;
if gmax[v]+len[i]<fmin[u,1] then
begin
fmin[u,2]:=fmin[u,1];
fminp[u,2]:=fminp[u,1];
fmin[u,1]:=gmax[v]+len[i];
fminp[u,1]:=v;
end
else
if gmax[v]+len[i]<fmin[u,2] then
begin
fmin[u,2]:=gmax[v]+len[i];
fminp[u,2]:=v;
end;
end;
i:=next[i];
end;
if fmax[u,2]=300000000000000 then fmax[u,2]:=0;
if fmin[u,2]=300000000000000 then fmin[u,2]:=0;
i:=head[u];
while i<>0 do
begin
v:=ret[i];
if v<>pre then
find(v,u,len[i]);
i:=next[i];
end;
end;
begin
readln(n);
for i:=1 to n do
gmin[i]:=30000000000000;
for i:=1 to n-1 do
begin
readln(u,v,l);
ins(u,v,l);
ins(v,u,l);
end;
dfs(1,-1);
fmax[-1,1]:=300000000000000;
fmax[-1,2]:=300000000000000;
find(1,-1,0);
for i:=1 to n do
writeln(ans[i]);
end.