题意:在一棵树上,找出一个节点,使得每一个节点到达该点的距离(权值*路径长度)和最短。
分析:先dfs求出每一个节点到根节点的距离和,然后再一次深搜即可。
交了之后悲剧的爆栈了,递归太是太深了,所以,开挂了,哈
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 100010;
#pragma comment(linker, "/STACK:1024000000,1024000000")
//开挂了,嘿嘿
struct edge
{
int v,w;
edge(){}
edge(int a,int b):v(a),w(b){}
};
vector<edge> g[N];
int n,tn[N],t[N];
//t[N]表示每一个节点的权值,tn[]表示子树的权值和
__int64 dist[N];
bool vis[N];
void init()
{
for(int i=0;i<=n;i++)
g[i].clear();
memset(vis,false,sizeof(vis));
memset(dist,0,sizeof(dist));
}
void dfs(int u,int dis)
{
vis[u]=true;
dist[1]+=1ll*dis*t[u];
tn[u]=t[u];
int size=g[u].size();
for(int i=0;i<size;i++)
{
int v=g[u][i].v;
if(vis[v]) continue;
dfs(v,dis+g[u][i].w);
tn[u]+=tn[v];
}
}
void dfs1(int u)
{
vis[u]=true;
int size=g[u].size();
for(int i=0;i<size;i++)
{
int v=g[u][i].v,w=g[u][i].w;
if(vis[v]) continue;
dist[v]=dist[u]+1ll*(tn[1]-2*tn[v])*w;
dfs1(v);
}
}
int main()
{
int x,y,w;
while(scanf("%d",&n)==1)
{
init();
for(int i=1;i<=n;i++)
scanf("%d",&t[i]);
for(int i=1;i<n;i++)
{
scanf("%d %d %d",&x,&y,&w);
g[x].push_back(edge(y,w));
g[y].push_back(edge(x,w));
}
dfs(1,0);
memset(vis,false,sizeof(vis));
dfs1(1);
__int64 ans=dist[1];
for(int i=2;i<=n;i++)
{
ans=min(ans,dist[i]);
}
printf("%I64d\n",ans);
}
return 0;
}