[BZOJ2435] [Noi2011]道路修建

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=2435

题目大意

给定一棵树,对于每一条边,对于答案的贡献为边长*abs(所连两点两边的点数差)

题解

任取个点转成有根树,BFS一次,得到每个点自己和子节点的个数和,我们知道,对于每条边所连两个点,一定是父节点和子节点,所以子节点下面的节点数一定比父节点少,知道子节点数a,剩下的点数就是n-a,然后计算即可

var
 w:array[0..3000000,1..3]of longint;
 x,y:array[0..1000000]of longint;
 t:array[0..1000000,1..2]of longint;
 z:array[0..1000000,1..3]of longint;
 i,j,k:longint;
 n,len,tail,tt:longint;
 a,b,c:longint;
 ans:int64;
procedure init(a,b,c:longint);
begin
 w[len,1]:=b; w[len,2]:=c;
 if w[a,3]=0
 then w[a,3]:=len else w[w[a,1],3]:=len;
 w[a,1]:=len; inc(len);
end;

begin
 readln(n); len:=n+1; ans:=0;
 for i:=1 to n-1 do
  begin readln(a,b,c); init(a,b,c); init(b,a,c); z[i,1]:=a; z[i,2]:=b; z[i,3]:=c; end;
 fillchar(y,sizeof(y),0);
 t[1,1]:=1; t[1,2]:=0; tail:=1; y[1]:=1;
 for i:=1 to n do
  begin
   tt:=w[t[i,1],3];
   while tt<>0 do
    begin
     if y[w[tt,1]]=0
     then begin inc(tail); t[tail,1]:=w[tt,1]; t[tail,2]:=t[i,1]; y[w[tt,1]]:=1; end;
     tt:=w[tt,3];
    end;
  end;
 for i:=1 to n do
  x[i]:=1;
 for i:=n downto 1 do
  inc(x[t[i,2]],x[t[i,1]]);
 for i:=1 to n-1 do
  begin
   a:=z[i,1]; b:=z[i,2]; c:=z[i,3];
   if x[a]<x[b] then j:=x[a] else j:=x[b];
   k:=n-j; a:=abs(k-j);
   inc(ans,int64(a)*int64(c));
  end;
 writeln(ans);
end.
    原文作者:道路修建问题
    原文地址: https://blog.csdn.net/slongle_amazing/article/details/49032819
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞