很好的一道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.