题目描述
题目大意
给定一张无向图
G=(n,n−1)
G
=
(
n
,
n
−
1
)
,每个点上有一定的人,选定一个点,使得所有人走到那里的代价最小。
解题思路
30分思路 最短路,
O(n3)
O
(
n
3
)
30~60分思路 最短路
O(n2logn)
O
(
n
2
l
o
g
n
)
60分思路 从每个点出发
dfs
d
f
s
遍历
O(n2)
O
(
n
2
)
100分思路 从1节点出发
dfs
d
f
s
遍历,再根据结果进行递推,复杂度
O(n)
O
(
n
)
100分代码
#include<cstdio>
#include<cstring>
#define N 100001
#define M 200001
using namespace std;
struct node{
int next,to,w;}e[M];
int l[M],a[N],n,tot,ansi;
long long ans=
2147483647456465234557ll,f[N],rs[N],jl[N];
bool vis[N];
void add(
int u,
int v,
int w)
{
e[tot]={l[u],v,w};l[u]=tot++;
e[tot]={l[v],u,w};l[v]=tot++;
return;
}
void dfs(
int x,
int dep)
{
vis[x]=
true;
jl[x]=a[x]*dep;rs[x]=a[x];
for(
int i=l[x];~i;i=e[i].next)
{
int y=e[i].to;
if(!vis[y]) dfs(y,dep+e[i].w),jl[x]+=jl[y],rs[x]+=rs[y];
}
}
void fdfs(
int x,
int fa,
int w)
{
vis[x]=
true;
if(x!=
1) f[x]=f[fa]+rs[
1]*w-
2*rs[x]*w;
if(f[x]<ans) {ans=f[x];ansi=x;}
for(
int i=l[x];~i;i=e[i].next)
{
int y=e[i].to;
if(!vis[y]) fdfs(y,x,e[i].w);
}
}
int main()
{
memset(l,-
1,
sizeof(l));
scanf(
"%d",&n);
for(
int i=
1;i<=n;i++)
scanf(
"%d",&a[i]);
for(
int i=
1,x,y,z;i<n;i++)
scanf(
"%d%d%d",&x,&y,&z),add(x,y,z);
dfs(
1,
0);
memset(vis,
0,
sizeof(vis));
f[
0]=
1e9;
f[
1]=jl[
1];
fdfs(
1,
0,
0);
printf(
"%d\n%lld",ansi,ans);
}