树状DP;
题目地址:http://acm.fzu.edu.cn/problem.php?pid=2038
题目意思是求任意两点距离的总和;
以每条边为对象,过这条边的总次数是 边左侧点的个数t乘以边右边点的个数n-t 所以这条边的累计和
边权v*t*(n-t);
因为此图为一棵树,所以可以用dfs在o(n)的时间内求出结果
#include
<cstdio>
#include
<vector>
#include
<memory.h>
#include
<iostream>
using
namespace std
;
const
int MAX
=
100100
;
_int64 r
;
_
int n
;
int deep
[
100009
];
struct
node
{
int e
;
__int64 v
;
node
(
int a
,
int b
)
{
e
=a
, v
=b
;
}
}
;
bool visit
[MAX
];
vector
<node
> edge
[MAX
];
_int64
dfs
(
int x
)
{
_
visit
[x
]=
true
;
int l
=edge
[x
].
size
();
__int64 t
;
__int64 sum
=
1
;
for
(
int i
=
0
;i
<l
;i
++)
{
int e
=edge
[x
][i
].e
;
if
(visit
[e
])
continue
;
/边右边点的个数 t
=
dfs
(e
);
/
r
+=edge
[x
][i
].v
*(n
-t
)*t
*
2
;
sum
+=t
;
}
return sum
;
}
int
main
()
{
int T
, i
, a
, b
, Case
=
0
;
__int64 c
;
scanf
(
"%d"
,
&T
);
while
(T
--)
{
Case
++;
scanf
(
"%d"
,
&n
);
for
(i
=
0
;i
<n
;i
++)
edge
[i
].
clear
();
memset
(visit
,
0
,
sizeof
(visit
));
for
(i
=
1
;i
<n
;i
++)
{
scanf
(
"%d %d %I64d"
,
&a
,
&b
,
&c
);
edge
[a
].
push_back
(
node
(b
, c
));
edge
[b
].
push_back
(
node
(a
, c
));
/建图过程
}
/
/总权值 r
=
0
;
/
/从0点开始搜索
dfs
(
0
);
/
printf
(
"Case %d: %I64d
\n
"
, Case
, r
);
}
return
0
;
}