• 【NOIP2016练习】T2 旅行(树形DP,换根)


    题意:小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旅行的路径长度。

    对于100%的数据,N ≤ 300000, c[i] ≤ 1e9

    对于60%的数据,N ≤ 3000

    思路:对于60分,容易想到枚举根,做N次O(N)的DP,时间复杂度O(n)

            对于100分,模拟样例后发现两个直接相连的节点U与V,其DP值只有U与V点时不同,所以考虑当根从U到V时O(1)转移求出新的DP[u]与DP[v]

            注意此处不需要保证整个DP数组值都为正确,只要U的值与V的值正确即可

            可以想到当U的最值由V转移时,两者交换后V必须从U的另一支转移,所以记录次值

            调参大法好

            

      1 var f:array[1..300000,1..4]of int64;
      2     ans:array[1..300000]of int64;
      3     head,vet,next,len,flag:array[1..600000]of longint;
      4     n,tot,i,x,y,z:longint;
      5     oo:int64;
      6 
      7 procedure add(a,b,c:longint);
      8 begin
      9  inc(tot);
     10  next[tot]:=head[a];
     11  vet[tot]:=b;
     12  len[tot]:=c;
     13  head[a]:=tot;
     14 end;
     15 
     16 procedure dfs(u:longint);
     17 var e,v,de:longint;
     18     t:int64;
     19 begin
     20  flag[u]:=1;
     21  e:=head[u];
     22  de:=0;
     23  while e<>0 do
     24  begin
     25   v:=vet[e];
     26   if flag[v]=0 then
     27   begin
     28    dfs(v); inc(de);
     29    t:=f[v,3]+len[e];
     30    if (t>f[u,1])or(f[u,1]=0) then
     31    begin
     32     f[u,2]:=f[u,1]; f[u,1]:=t;
     33    end
     34     else if (t<=f[u,1])and(t>f[u,2])or(f[u,2]=0) then f[u,2]:=t;
     35 
     36    t:=f[v,1]+len[e];
     37    if (t<f[u,3])or(f[u,3]=0) then
     38    begin
     39     f[u,4]:=f[u,3]; f[u,3]:=t;
     40    end
     41     else if (t>=f[u,3])and(t<f[u,4])or(f[u,4]=0) then f[u,4]:=t;
     42 
     43   end;
     44   e:=next[e];
     45  end;
     46 
     47 end;
     48 
     49 procedure change(u:longint);
     50 var e,v:longint;
     51     t,t1,t2,t3,t4:int64;
     52 begin
     53  e:=head[u]; flag[u]:=1;
     54  t1:=f[u,1]; t2:=f[u,2]; t3:=f[u,3]; t4:=f[u,4];
     55 
     56  ans[u]:=f[u,1];
     57  while e<>0 do
     58  begin
     59   v:=vet[e];
     60 
     61   if flag[v]=1 then begin e:=next[e]; continue; end;
     62    if f[v,3]+len[e]=t1 then t:=f[u,2]+len[e]
     63    else t:=f[u,1]+len[e];
     64    if (t<f[v,3])or(f[v,3]=0) then
     65   begin
     66    f[v,4]:=f[v,3]; f[v,3]:=t;
     67   end
     68    else if (t<f[v,4])or(f[v,4]=0) then f[v,4]:=t;
     69 
     70   if f[v,1]+len[e]=t3 then begin t:=f[u,4]+len[e];end
     71    else t:=f[u,3]+len[e];
     72 
     73 
     74   if (t>f[v,1])or(f[v,1]=0) then
     75   begin
     76    f[v,2]:=f[v,1]; f[v,1]:=t;
     77   end
     78    else if (t>f[v,2])or(f[v,2]=0) then f[v,2]:=t;
     79   change(v);
     80   e:=next[e];
     81  end;
     82 
     83 
     84 end;
     85 
     86 begin
     87  assign(input,'travel.in'); reset(input);
     88  assign(output,'travel.out'); rewrite(output);
     89  oo:=1<<63;
     90  readln(n);      //f[u,1]zuida f[u,2]cida
     91                  //f[u,3]zuixiao f[u,4]cixiao
     92  for i:=1 to n-1 do
     93  begin
     94   readln(x,y,z);
     95   add(x,y,z);
     96   add(y,x,z);
     97  end;
     98 
     99  dfs(1);
    100  fillchar(flag,sizeof(flag),0);
    101  change(1);
    102  for i:=1 to n do writeln(ans[i]);
    103  close(input);
    104  close(output);
    105 end.

      

       

  • 相关阅读:
    spring+mybatis多数据源切换
    【linux环境下】RabbitMq的安装和监控插件安装
    Slurm远程登录Jupyter Notebook
    Google Colab 使用
    关于conda和jupyter使用
    关于给C盘扩容以及动态磁盘
    关于使用实验室服务器的GPU以及跑上TensorFlow代码
    一些更改的后端接口和代码
    MarkDown to PDF
    蜗牛慢慢爬 LeetCode 25. Reverse Nodes in k-Group [Difficulty: Hard]
  • 原文地址:https://www.cnblogs.com/myx12345/p/5993517.html
Copyright © 2020-2023  润新知