【题目】
Codeforces
给出一棵
n
n
n个点带正权
w
i
w_i
wi且互不相同的树,满足
除了权值最小的点,每个点
u
u
u都至少有一个相邻点
v
v
v满足
w
u
>
w
v
w_u>w_v
wu>wv。
现在要求另构造一棵树最小化代价:
- 对于每个点 u u u产生 d e g u ⋅ w u deg_u\cdot w_u degu⋅wu的代价, d e g u deg_u degu为构造的树中点 u u u的度数
- 对于构造树中每条边
(
u
,
v
)
(u,v)
(u,v),产生
⌈
log
2
d
i
s
(
u
,
v
)
⌉
⋅
min
{
w
u
,
w
v
}
\lceil \log_2dis(u,v)\rceil \cdot \min \{w_u,w_v\}
⌈log2dis(u,v)⌉⋅min{wu,wv}的代价,其中
d
i
s
(
u
,
v
)
dis(u,v)
dis(u,v)是给出的树中
u
,
v
u,v
u,v的距离
输出这个代价。
n ≤ 5 × 1 0 5 n\leq 5\times 10^5 n≤5×105
【解题思路】
给出树那个奇怪的限制告诉我们:以
w
i
w_i
wi最小的点为根时,每个节点的父亲都比它小,即满足小根堆性质。
代价分开太难统计了,不妨考虑将点的代价放到边上考虑,那么一条边
(
u
,
v
)
(u,v)
(u,v)的代价就是:
(
⌈
log
2
d
i
s
(
u
,
v
)
⌉
+
1
)
⋅
min
{
w
u
,
w
v
}
+
max
{
w
u
,
w
v
}
(\lceil \log_2 dis(u,v) \rceil +1) \cdot \min \{w_u,w_v\} + \max \{w_u,w_v\}
(⌈log2dis(u,v)⌉+1)⋅min{wu,wv}+max{wu,wv}
现在我们考虑 Kruskal \text{Kruskal} Kruskal算法,一个点连出去的最小的边一定在 MST \text{MST} MST中。那么根据上面哪个柿子,以及题目的小根堆性质,一个节点连出去的边一定是它的 2 k 2^k 2k级祖先或根节点。于是我们可以枚举它与哪个点相连,选择最小的一条即可。
复杂度 O ( n log n ) O(n\log n) O(nlogn)
【参考代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
const ll inf=1e18;
int read()
{
int ret=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return ret;
}
namespace DreamLolita
{
int n,rt,tot;
int head[N],w[N],fa[20][N];
ll ans;
struct Tway{int v,nex;}e[N<<1];
void add(int u,int v)
{
e[++tot]=(Tway){v,head[u]};head[u]=tot;
e[++tot]=(Tway){u,head[v]};head[v]=tot;
}
void dfs(int x)
{
if(x^rt)
{
int j=0;ll res=inf;
for(j=1;fa[j-1][fa[j-1][x]];++j) fa[j][x]=fa[j-1][fa[j-1][x]];
for(j=0;fa[j][x];++j) res=min(res,1ll*(j+1)*w[fa[j][x]]+w[x]);
res=min(res,1ll*(j+1)*w[rt]+w[x]);ans+=res;
}
for(int i=head[x];i;i=e[i].nex)
{
int v=e[i].v;
if(v==fa[0][x]) continue;
fa[0][v]=x;dfs(v);
}
}
void solution()
{
n=read();w[0]=2e9;
for(int i=1;i<=n;++i) w[i]=read(),rt=w[i]<w[rt]?i:rt;
for(int i=1;i<n;++i) add(read(),read());
dfs(rt);
printf("%lld\n",ans);
}
}
int main()
{
#ifdef Durant_Lee
freopen("CF1088F.in","r",stdin);
freopen("CF1088F.out","w",stdout);
#endif
DreamLolita::solution();
return 0;
}