算法:搜索
一开始把树结构看成图了,结果只过了一个点,仔细一看,才能发现这确实是一个考察树的题目(n个点n-1条边),题目中我们需要确定的就是子结点与父结点的关系。
首先,我们用up[i]表示不属于i的子树上的点的其它的所有点到i的距离和,用down[i]表示属于i的子树上的所有点到i的距离和。用sum[i]表示i的子结点的所有点的牛的数目。
down[dad]=down[i]+sum[i]*dis[i](这个比较好想)
up[i]=up[dad]+down[dad]-down[i]-sum[i]*dis[i]+(sumcow-sum[i])*dis[i](这个就比较难想了)
一开始把树结构看成图了,结果只过了一个点,仔细一看,才能发现这确实是一个考察树的题目(n个点n-1条边),题目中我们需要确定的就是子结点与父结点的关系。
首先,我们用up[i]表示不属于i的子树上的点的其它的所有点到i的距离和,用down[i]表示属于i的子树上的所有点到i的距离和。用sum[i]表示i的子结点的所有点的牛的数目。
down[dad]=down[i]+sum[i]*dis[i](这个比较好想)
up[i]=up[dad]+down[dad]-down[i]-sum[i]*dis[i]+(sumcow-sum[i])*dis[i](这个就比较难想了)
用双向边建图,然后搜索两次,最后枚举就得出答案了……
program gather;
const
maxn=100000;
type
atp=record
y,next,dis:int64;
end;
var
n,tot:int64;
sumcow,ans:int64;
a,first:array [0..maxn] of int64;
sum,up,down:array [0..maxn] of int64;
map:array [0..maxn*2] of atp;
procedure init;
var
i,x,y:longint;
dis:int64;
begin
ans:=2147483647000;
readln(n);
for i:=1 to n do
begin
readln(a[i]);
inc(sumcow,a[i]);
end;
for i:=1 to n-1 do
begin
readln(x,y,dis);
inc(tot);
map[tot].y:=y;
map[tot].dis:=dis;
map[tot].next:=first[x];
first[x]:=tot;
inc(tot);
map[tot].y:=x;
map[tot].dis:=dis;
map[tot].next:=first[y];
first[y]:=tot;
end;
end;
procedure dfs1(x,bef:longint);
var
t:longint;
begin
t:=first[x];
sum[x]:=a[x];
while t>0 do
begin
if map[t].y<>bef then
begin
dfs1(map[t].y,x);
inc(sum[x],sum[map[t].y]);
inc(down[x],sum[map[t].y]*map[t].dis);
inc(down[x],down[map[t].y]);
end;
t:=map[t].next;
end;
end;
procedure dfs2(x,bef:longint);
var
t:longint;
begin
t:=first[x];
while t>0 do
begin
if map[t].y<>bef then
begin
up[map[t].y]:=up[x]+down[x]-down[map[t].y]-sum[map[t].y]*map[t].dis+(sumcow-sum[map[t].y])*map[t].dis;
dfs2(map[t].y,x);
end;
t:=map[t].next;
end;
end;
procedure main;
var
i:longint;
begin
dfs1(1,0);
dfs2(1,0);
for i:=1 to n do if up[i]+down[i]<ans then ans:=up[i]+down[i];
end;
begin
assign(input,'gather.in'); reset(input);
assign(output,'gather.out'); rewrite(output);
init;
main;
writeln(ans);
close(input); close(output);
end.
本文介绍了一种在树形结构中计算每个节点与其子节点间距离之和的算法。通过定义up[i]和down[i]来分别记录不属于i节点子树的其他节点到i节点的距离总和以及i节点子树上所有节点到i节点的距离总和。利用DFS两次遍历实现计算,并最终找到最小距离和的节点。
499

被折叠的 条评论
为什么被折叠?



