旅行

来源:互联网 发布:淘宝 雅诗兰黛 小样 假 编辑:程序博客网 时间:2024/04/27 15:30

题目描述 小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] 表示向上走向下走最大最小值,转移同理,详见代码。

vartot,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);vari,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);vari,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.
0 0