一 原题
Sonya likes ice cream very much. She eats it even during programming competitions. That is why the girl decided that she wants to open her own ice cream shops.
Sonya lives in a city with nn junctions and n−1n−1 streets between them. All streets are two-way and connect two junctions. It is possible to travel from any junction to any other using one or more streets. City Hall allows opening shops only on junctions. The girl cannot open shops in the middle of streets.
Sonya has exactly kk friends whom she can trust. If she opens a shop, one of her friends has to work there and not to allow anybody to eat an ice cream not paying for it. Since Sonya does not want to skip an important competition, she will not work in shops personally.
Sonya wants all her ice cream shops to form a simple path of the length rr (1≤r≤k1≤r≤k), i.e. to be located in different junctions f1,f2,…,frf1,f2,…,fr and there is street between fifi and fi+1fi+1 for each ii from 11 to r−1r−1.
The girl takes care of potential buyers, so she also wants to minimize the maximum distance between the junctions to the nearest ice cream shop. The distance between two junctions aa and bb is equal to the sum of all the street lengths that you need to pass to get from the junction aa to the junction bb. So Sonya wants to minimize
maxamin1≤i≤rda,fimaxamin1≤i≤rda,fi
where aa takes a value of all possible nn junctions, fifi — the junction where the ii-th Sonya's shop is located, and dx,ydx,y — the distance between the junctions xx and yy.
Sonya is not sure that she can find the optimal shops locations, that is why she is asking you to help her to open not more than kk shops that will form a simple path and the maximum distance between any junction and the nearest shop would be minimal.
The first line contains two integers nn and kk (1≤k≤n≤1051≤k≤n≤105) — the number of junctions and friends respectively.
Each of the next n−1n−1 lines contains three integers uiui, vivi, and didi (1≤ui,vi≤n1≤ui,vi≤n, vi≠uivi≠ui, 1≤d≤1041≤d≤104) — junctions that are connected by a street and the length of this street. It is guaranteed that each pair of junctions is connected by at most one street. It is guaranteed that you can get from any junctions to any other.
Print one number — the minimal possible maximum distance that you need to pass to get from any junction to the nearest ice cream shop. Sonya's shops must form a simple path and the number of shops must be at most kk.
6 2 1 2 3 2 3 4 4 5 2 4 6 3 2 4 6
4
10 3 1 2 5 5 7 2 3 2 6 10 6 3 3 8 1 6 4 2 4 1 6 6 9 4 5 2 5
7
In the first example, you can choose the path 2-4, so the answer will be 4.

In the second example, you can choose the path 4-1-2, so the answer will be 7.

二 分析
给你一棵n个点的树,要求从树上找一条简单路径,路径上的点数不超过k,使得剩余的点到这条路径上的点的最大距离最小。比如图2,选取的点是{1, 2, 4},剩余最远的点是7和8,距离都是7,这是最优解。
可以证明这k个点都必须在树的直径上,为直径上的每个点i求两个值:d1(i)代表i到直径左端点的距离,d2(i)代表去除直径上的点后,i为根的子树中的点到i的最大距离。最多在直径上选k个点,相当于一个长度为k的区间在直径上滑动,每个区间对应的值是:
内层的max就是一个在d2数组上滑动窗口最大值的问题。
三 代码
/*
ID: maxkkibble
LANG: c++
PROB: cf 1004E
*/
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
// #define LOCAL
#define pb push_back
#define fi first
#define se second
typedef pair<int, int> PII;
const int maxn = 1e5 + 5;
int n, k;
vector<PII> g[maxn];
bool vis[maxn]; // useless util calc vector d2
int mx, id, pre[maxn], dis[maxn];
void dfs(int x, int fa) {
pre[x] = fa;
for (PII e: g[x]) {
if (e.fi == fa || vis[e.fi]) continue;
dis[e.fi] = dis[x] + e.se;
if (dis[e.fi] > mx) mx = dis[e.fi], id = e.fi;
dfs(e.fi, x);
}
}
vector<int> dia, d1, d2;
int dia_len;
void calcDiameter() {
int st, ed;
mx = 0, id = 1;
dfs(1, 0);
st = id;
mx = 0, id = st;
dfs(st, dis[st] = 0);
ed = id, dia_len = mx;
while (ed != 0) {
dia.pb(ed);
d1.pb(dia_len - dis[ed]);
vis[ed] = true;
ed = pre[ed];
}
for (int i = 0; i < dia.size(); i++) {
mx = 0, id = dia[i];
dfs(dia[i], dis[dia[i]] = 0);
d2.push_back(mx);
}
}
int main() {
#ifdef LOCAL
freopen("e.in", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin >> n >> k;
for (int i = 0; i < n - 1; i++) {
int s, e, l;
cin >> s >> e >> l;
g[s].pb({e, l});
g[e].pb({s, l});
}
calcDiameter();
deque<PII> q;
k = min(k, (int)dia.size());
int ans = 1e9 + 5;
for (int i = 0, j = 0; i <= dia.size() - k; i++) {
while (j <= i + k - 1) {
while (!q.empty() && d2[j] > q.back().fi)
q.pop_back();
q.push_back({d2[j], j});
j++;
}
while (q.front().se < i) q.pop_front();
int tmp = max({q.front().fi, d1[i], dia_len - d1[i + k -1]});
ans = min(ans, tmp);
}
cout << ans << endl;
return 0;
}