ABC222 F - Expensive Expense(树的直径)
目录
Description
有一棵树,求每一个节点到其他节点的最短路径的最大值,\(dis(i,j)\),定义为 \(i\) 节点至 \(j\) 节点的边权之和以及终点 \(j\) 的点权
State
\(1<=n<=2*10^5\)
\(1<=a_i<=n\)
\(1<=b_i<=n\)
\(1<=c_i<=10^9\)
\(1<=d_i<=10^9\)
Input
6
1 2 3
1 3 1
1 4 4
1 5 1
1 6 5
9 2 6 5 3 100
Output
105
108
106
109
106
14
Solution
小技巧:如果将点权转化成边权,每一个节点将不会再有点权,即添加边 \((i, i+n)\)
在树中,如果求一个点 \(i\) 的最长路径,一定是点 \(i\) 到达该树直径的两个端点的其中一个
现在我们需要知道的是任意一个点到达这两个端点的距离,答案即为 \(max(a[i], b[i])\)
$hint: $ 如果该点处于端点位置,那么该点的答案一定是到达另一个端点的距离,因为题目不考虑起点的点权
Code
const int N = 4e5 + 5;
int n, m, k, _;
vector<pii> G[N];
ll a[N];
ll b[N];
struct Node
{
int u, v, w;
void read(){ sddd(u, v, w); }
}t[N];
void add(int u, int v, int w)
{
G[u].pb(mp(v, w));
G[v].pb(mp(u, w));
}
void dfs(int u, int fa, ll *d, ll w)
{
d[u] = d[fa] + w;
int sz = G[u].size();
for(int i = 0; i < sz; i ++){
int v = G[u][i].fi;
int w = G[u][i].se;
if(v == fa) continue;
dfs(v, u, d, w);
}
}
signed main()
{
// IOS;
while(~ sd(n)){
rep(i, 1, n - 1){
t[i].read();
add(t[i].u, t[i].v, t[i].w);
}
rep(i, 1, n){
int x = read();
t[i + n - 1] = {i, i + n, x};
add(t[i + n - 1].u, t[i + n - 1].v, t[i + n - 1].w);
}
m = n + n;
dfs(1, 0, a, 0);
int p = max_element(a + 1, a + 1 + m) - a;
dfs(p, 0, a, 0);
int q = max_element(a + 1, a + 1 + m) - a;
dfs(q, 0, b, 0);
for(int i = 1; i <= n; i ++){
if(i == p - n) pll(b[i]);
else if(i == q - n) pll(a[i]);
else pll(max(a[i], b[i]));
}
}
// PAUSE;
return 0;
}

浙公网安备 33010602011771号