[dfs] Jzoj P1497 景点中心
题解
- 先可以定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\n%lld",ans,mn); 47 return 0; 48 }