题解
- 先可以定i为根,用dfs求出从i到根结点的价值和子树大小
- 那么求完之后就可以求出所有点到i的距离
- 设在A处集合时,所有人走的距离的和为B
- 若C是A的儿子则所有人在C处集合的走的距离是C=B+(该边权值)*(总人数-2*size[C])
代码
1 #include<cstdio>
2 #include<iostream>
3 using namespace std;
4 struct edge {int to,from,v; }e[100010*2];
5 int head[100010],n,cnt=1;
6 long long size[100010],dis[100010],mn,ans;
7 void insert(int x,int y,int v) { e[cnt].to=y; e[cnt].v=v; e[cnt].from=head[x]; head[x]=cnt++; }
8 void dfs(int x,int fa)
9 {
10 for (int i=head[x];i;i=e[i].from)
11 if (e[i].to!=fa)
12 {
13 dfs(e[i].to,x);
14 size[x]+=size[e[i].to];
15 dis[x]+=dis[e[i].to]+size[e[i].to]*e[i].v;
16 }
17 }
18 void dfs1(int x,int fa)
19 {
20 for (int i=head[x];i;i=e[i].from)
21 if (e[i].to!=fa)
22 {
23 dis[e[i].to]=dis[x]+e[i].v*(size[1]-2*size[e[i].to]);
24 dfs1(e[i].to,x);
25 }
26 }
27 int main()
28 {
29 scanf("%d",&n);
30 for (int i=1;i<=n;i++) scanf("%lld",&size[i]);
31 for (int i=1;i<=n-1;i++)
32 {
33 int x,y,v;
34 scanf("%d%d%d",&x,&y,&v);
35 insert(x,y,v); insert(y,x,v);
36 }
37 dfs(1,0);
38 dfs1(1,0);
39 mn=10000000000000;
40 for (int i=1;i<=n;i++)
41 if (mn>dis[i])
42 {
43 mn=dis[i];
44 ans=i;
45 }
46 printf("%lld
%lld",ans,mn);
47 return 0;
48 }