传送门

题意

有一棵 nn 个节点的以 ss 为根的树。每条树边都有一个长度。每次操作可以把一条树边的长度加 11

问:至少操作多少次,可以使根节点到每个叶子节点的距离相等。

结论 11

对于任意子树,其根节点到其每个叶子节点的距离相等。

证明
反证法。
设对于根为 RR 的树的根为 rr 的某一子树,有两个叶子 aabbrr 的距离不等。
那么不妨设节点 xxyy 间的距离为 dis(x,y)dis(x,y),则有

dis(a,r)dis(b,r)dis(a,r)\not=dis(b,r)

所以

dis(a,r)+dis(r,R)dis(b,r)+dis(r,R)dis(a,r)+dis(r,R)\not=dis(b,r)+dis(r,R)

dis(a,R)dis(b,R)dis(a,R)\not=dis(b,R)

aabbRR 的距离不等。这与题目条件矛盾,所以命题成立。

解法

既然结论 11 成立,那么先从最简单的情况入手。

如图,在这一棵以 11 为根的树中,在操作后,根节点 11 到叶子的距离最小是几?

图 1

很明显的,这个值应该是所有叶子到根的所有距离的最大值。

那么对于每个节点都实行此原则,就结束了。

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <bits/stdc++.h>
using namespace std;

using uint = unsigned;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;

#define int ll

int hd[500005<<1],nxt[500005<<1],to[500005<<1],we[500005<<1],et=0;
inline void adde(int u,int v,int w) { ++et,to[et]=v,we[et]=w,nxt[et]=hd[u],hd[u]=et; }
int n,s,ans,dp[500005];

void dfs(int u,int fa) {
int mx=0,tot=0;
for(int i=hd[u],v,t; v=to[i],t=we[i],i; i=nxt[i]) {
if(v==fa) continue;
dfs(v,u);
if(dp[v]+t>mx) {
ans+=(dp[v]+t-mx)*tot;
mx=dp[v]+t;
} else ans+=(mx-dp[v]-t);
++tot;
}
dp[u]=mx;
}

signed main() {
cin>>n>>s;
for(int i=1; i<n; ++i) {
int u,v,t;
cin>>u>>v>>t;
adde(u,v,t); adde(v,u,t);
}
dfs(s,0);
cout<<ans<<endl;
}