Sonya and Ice Cream(CF-1004E)

Problem Description

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 n junctions and n−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 k 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 r (1≤r≤k), i.e. to be located in different junctions f1,f2,…,fr and there is street between fi and fi+1 for each ii from 1 to r−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 b. So Sonya wants to minimize

maxamin1≤i≤rda,fi

where a takes a value of all possible n junctions, fi — the junction where the ii-th Sonya's shop is located, and dx,y — the distance between the junctions x and y.

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 k shops that will form a simple path and the maximum distance between any junction and the nearest shop would be minimal.

Input

The first line contains two integers n and k (1≤k≤n≤105) — the number of junctions and friends respectively.

Each of the next n−1 lines contains three integers ui, vi, and di (1≤ui,vi≤n, vi≠ui, 1≤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.

Output

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 k.

Examples

Input

6 2
1 2 3
2 3 4
4 5 2
4 6 3
2 4 6

Output

4

Input

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

Output

7

Note

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

Sonya and Ice Cream(CF-1004E)_第1张图片

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

Sonya and Ice Cream(CF-1004E)_第2张图片

题意:有一棵 n 个点的树,给出这棵树的 n-1 条边的权值,现在要在这棵树上找一条具有 k 个点的简单路径,使得树上剩余的点到这条路径的最大距离最小

思路:

我们知道,树的直径是树中最远的两个节点的距离,因此,要想要选择连续的 k 个点,那么必定有一个点,要将直径截断,而这个点一定位于树的直径上

那么,接下来在寻找剩下的 k-1 个点,同样可以证明其均位于树的直径上,那么问题就变成了在树的直径上找一个长度为 k 的简单路径,使得其他点到这条路径的最大距离最小

树的直径 diameter 我们可以用两遍 dfs 来求,同时在为树的直径上的第 i 个点求两个值:

  • dis1[i]:i 到直径左端点的距离
  • dis2[i]:除去直径上的点后,以点 i 为根的子树中的点到点 i 的距离

此时,由于要在树的直径上找一条 k 个点的简单路径,相当于一个长度为 k 的区间在直径上进行滑动,而对于这个长度为 k 的区间来说,其值为:

max\{dis1[i],diameter-dis1[i+k-1],max\{dis2[i],dis[i+1],...,dis[i+k-1]\}\}

内层的 max\{dis2[i],dis[i+1],...,dis[i+k-1]\} 本质上是一个滑动窗口问题,可以利用单调队列来解决。

Source Program

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL multMod(LL a,LL b,LL mod){ a%=mod; b%=mod; LL res=0; while(b){if(b&1)res=(res+a)%mod; a=(a<<=1)%mod; b>>=1; } return res%mod;}
LL quickMultPowMod(LL a, LL b,LL mod){ LL res=1,k=a; while(b){if((b&1))res=multMod(res,k,mod)%mod; k=multMod(k,k,mod)%mod; b>>=1;} return res%mod;}
LL quickPowMod(LL a,LL b,LL mod){ LL res=1; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1; } return res; }
LL getInv(LL a,LL mod){ return quickPowMod(a,mod-2,mod); }
LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); }
LL LCM(LL x,LL y){ return x/GCD(x,y)*y; }
const double EPS = 1E-6;
const int MOD = 1000000000+7;
const int N = 100000+5;
const int dx[] = {0,0,-1,1,1,-1,1,1};
const int dy[] = {1,-1,0,0,-1,1,-1,1};
using namespace std;

struct Edge {
    int to, val;
    Edge() {}
    Edge(int to, int val) : to(to), val(val) {}
};
int n, k;
vector edge[N];
int Next[N], dis[N], maxx, id;
bool vis[N];
int diameter;
vector diameterNum, dis1, dis2;
void dfs(int x, int father) {
    Next[x] = father;
    for (int i = 0; i < edge[x].size(); i++) {
        int y = edge[x][i].to;
        int val = edge[x][i].val;
        if (y == father || vis[y])
            continue;
        dis[y] = dis[x] + val;
        if (dis[y] > maxx) {
            maxx = dis[y];
            id = y;
        }
        dfs(y, x);
    }
}
void calcDiameter() {
    //第一遍dfs
    maxx = 0;
    id = 1;
    dfs(1, 0);
    int st = id;

    //第二遍dfs
    maxx = 0;
    dis[st] = 0;
    dfs(st, 0);
    int ed = id;

    diameter = maxx; //树的直径

    //计算dis1
    while (ed != 0) {
        diameterNum.push_back(ed);
        dis1.push_back(diameter - dis[ed]);
        vis[ed] = true;
        ed = Next[ed];
    }

    //计算dis2
    for (int i = 0; i < diameterNum.size(); i++) {
        maxx = 0;
        id = diameterNum[i];
        dis[diameterNum[i]] = 0;
        dfs(diameterNum[i], 0);
        dis2.push_back(maxx);
    }
}
int slidingWindow() {
    deque Q;
    k = min(k, (int)diameterNum.size());
    int res = INF;
    for (int i = 0, j = 0; i <= diameterNum.size() - k; i++) {
        while (j <= i + k - 1) {
            while (!Q.empty() && dis2[j] > Q.back().to)
                Q.pop_back();
            Q.push_back(Edge(dis2[j], j));
            j++;
        }
        while (Q.front().val < i)
            Q.pop_front();
        int tmp = max({Q.front().to, dis1[i], diameter - dis1[i + k - 1]});
        res = min(res, tmp);
    }
    return res;
}
int main() {
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n - 1; i++) {
        int x, y, val;
        scanf("%d%d%d", &x, &y, &val);
        edge[x].push_back(Edge(y, val));
        edge[y].push_back(Edge(x, val));
    }
    memset(vis, false, sizeof(vis));
    
    calcDiameter();
    int res=slidingWindow();
    printf("%d\n", res);

    return 0;
}

 

你可能感兴趣的:(#,CodeForces,#,树形结构——树与二叉树)