zoukankan      html  css  js  c++  java
  • bzoj3124

    很好的一道treedp,当然也挺烦的
    首先不难想到先求出一个直径,然后穷举每条边,看他删除之后直径大小是否会变,变了的话就是必须经过的边
    下面我们就要想怎么优化,本人语言表达略差,还是配合程序说吧。

      1 type node=record
      2        point,next:longint;
      3        cost:int64;
      4      end;
      5 
      6 var f:array[0..200010] of int64;
      7     pr,fr:array[0..200010,0..2] of longint;
      8     g,h:array[0..200010,0..2] of int64;
      9     p:array[0..200010] of longint;
     10     edge:array[0..400010] of node;
     11     v:array[0..200010] of boolean;
     12     i,n,len,ans,x,y,z:longint;
     13 
     14 procedure add(x,y,z:longint);
     15   begin
     16     inc(len);
     17     edge[len].point:=y;
     18     edge[len].cost:=z;
     19     edge[len].next:=p[x];
     20     p[x]:=len;
     21   end;
     22 
     23 function max(a,b:int64):int64;
     24   begin
     25     if a>b then exit(a) else exit(b);
     26   end;
     27 
     28 procedure dp(x:longint);
     29   var i,y:longint;
     30   begin
     31     i:=p[x];
     32     v[x]:=true;
     33     while i<>-1 do
     34     begin
     35       y:=edge[i].point;
     36       if not v[y] then
     37       begin
     38         dp(y);
     39         f[x]:=max(f[x],f[y]);  //f[]表示以x为根的子树中最长的路径长
     40         if g[y,0]+edge[i].cost>g[x,0] then  //维护以x为根走到底最长的3条路径(显然不能有两条路径经过同一个孩子)
     41 //这里要维护3条,因为要考虑删边的时候碰巧干掉了其中一条,如果单纯求树的直径的时候只要维护最长和次长即可)
     42         begin
     43           g[x,2]:=g[x,1];
     44           fr[x,2]:=fr[x,1];
     45           g[x,1]:=g[x,0];
     46           fr[x,1]:=fr[x,0];
     47           g[x,0]:=g[y,0]+edge[i].cost;
     48           fr[x,0]:=y;  //从哪转移来的
     49         end
     50         else if (g[y,0]+edge[i].cost>g[x,1]) then
     51         begin
     52           g[x,2]:=g[x,1];
     53           fr[x,2]:=fr[x,1];
     54           g[x,1]:=g[y,0]+edge[i].cost;
     55           fr[x,1]:=y;
     56         end
     57         else if (g[y,0]+edge[i].cost>g[x,2]) then
     58         begin
     59           g[x,2]:=g[y,0]+edge[i].cost;
     60           fr[x,2]:=y;
     61         end;
     62         if f[y]>h[x,0] then  //h维护的是以x为根的子树中最长的2条路径(不经过根)
     63         begin
     64           h[x,1]:=h[x,0];
     65           pr[x,1]:=pr[x,0];
     66           h[x,0]:=f[y];
     67           pr[x,0]:=y;  //从哪转移来的
     68         end
     69         else if f[y]>h[x,1] then
     70         begin
     71           h[x,1]:=f[y];
     72           pr[x,1]:=y;
     73         end;
     74       end;
     75       i:=edge[i].next;
     76     end;
     77     f[x]:=max(f[x],g[x,1]+g[x,0]);
     78   end;
     79 
     80 procedure dfs(x:longint;l,d:int64); //l表示以x为终点且不是起点x的后辈的最长路径,d表示之前搜索到的不经过x的最长路径
     81   var i,y:longint;
     82       l1,l2,l3:int64;
     83   begin
     84     i:=p[x];
     85     v[x]:=true;
     86     while i<>-1 do
     87     begin
     88       y:=edge[i].point;
     89       if not v[y] then   //大批的分类讨论
     90       begin
     91         l1:=f[y];
     92         if y=pr[x,0] then l2:=h[x,1]
     93         else l2:=h[x,0];
     94         l2:=max(l2,d);
     95 
     96         if y=fr[x,0] then l2:=max(l2,g[x,1]+g[x,2])
     97         else if y=fr[x,1] then l2:=max(l2,g[x,0]+g[x,2])
     98         else l2:=max(l2,g[x,0]+g[x,1]);
     99 
    100         if y=fr[x,0] then l3:=g[x,1]
    101         else l3:=g[x,0];
    102         l2:=max(l2,l+l3);
    103         if max(l1,l2)<f[1] then inc(ans);
    104         dfs(y,max(l3,l)+edge[i].cost,l2);
    105       end;
    106       i:=edge[i].next;
    107     end;
    108   end;
    109 
    110 begin
    111   readln(n);
    112   fillchar(p,sizeof(p),255);
    113   for i:=1 to n-1 do
    114   begin
    115     readln(x,y,z);
    116     add(x,y,z);
    117     add(y,x,z);
    118   end;
    119   dp(1);
    120   writeln(f[1]);
    121   fillchar(v,sizeof(v),false);
    122   ans:=0;
    123   dfs(1,0,0);
    124   writeln(ans);
    125 end.
    View Code
  • 相关阅读:
    GDUFE ACM-1087
    背包九讲
    OJ4TH|Inverse number:Reborn
    OJ4TH|Let's play a game
    GG第四次作业
    OpenCV(3)其他常用数据类型
    OpenCV学习(2)读取视频和摄像头
    OpenCV(1)读写图像
    GG第三次作业
    GG第二次作业
  • 原文地址:https://www.cnblogs.com/phile/p/4473142.html
Copyright © 2011-2022 走看看