Description
给出一个树,树的边上有权值,现在要你求出一个满足下面三个要求的节点集合。
第一,根节点不在集合S中。
第二,集合中任何两个节点仅有一个公共祖先,即根节点。
第三,对集合中每个节点都要有两个值,wi表示到这个节点的路径上所有的边权值总和,di表示到这个节点的路径所包含的边数,现在要求sigma(wi)/sigma(di)的最大值。
Input
多组数据。
第一行一个数ca,表示有多少组测试数据。
对于每一组测试数据,第一行有一个整数N(1<=n<=1000),表示这棵树有多少个节点。
然后下面N-1行,每行有三个整树,x,y,z
(0<=x,y)
表示x,y之间有一条权值为z的边,编号为0的是根节点。
Output
对于每组测试数据,输出simga(wi)/sigma(di)的最大值,保留2位小数。
Sample Input
3
1
2
0 1 2
3
0 1 1
0 2 2
Sample Output
0.00
2.00
2.00
题解
先看题目,发现每棵以根节点的儿子的子树内只能选一个点或者不选。
观察答案的式子,发现当已知答案要合并另一个答案,只有两种情况:
1、原来两个答案相同,合并后不影响。
2、合并后的答案大于较小值,小于较大值。
因此得出结论:合并两个答案之后答案不上升。
因此最优情况一定是只选1个节点。
跑一遍bfs即可。
var tt,n,i,j,k,l,tot,x,y,z:longint;
dis,w,head,next,t,cc,q:array[0..100000]of longint;
p:array[0..100000]of boolean;
ans:real;
procedure ad(x,y,z:longint);
begin
inc(tot);
next[tot]:=head[x];
head[x]:=tot;
t[tot]:=y;
cc[tot]:=z;
end;
procedure bfs;
var i,j,k:longint;
begin
i:=0;
k:=1;
q[1]:=0;
p[0]:=true;
while i<k do begin
inc(i);
if (dis[q[i]]<>0)and(w[q[i]]/dis[q[i]]>ans) then ans:=w[q[i]]/dis[q[i]];
j:=head[q[i]];
while j<>0 do begin
if p[t[j]] then begin
j:=next[j];
continue;
end;
inc(k);
q[k]:=t[j];
p[t[j]]:=true;
w[t[j]]:=w[q[i]]+cc[j];
dis[t[j]]:=dis[q[i]]+1;
j:=next[j];
end;
end;
end;
begin
readln(tt);
while tt<>0 do begin
dec(tt);
readln(n);
tot:=0;
for i:=0 to n-1 do begin
head[i]:=0;
p[i]:=false;
end;
for i:=1 to n-1 do begin
readln(x,y,z);
ad(x,y,z);
ad(y,x,z);
end;
ans:=0;
bfs;
writeln(ans:0:2);
end;
end.