Problem:
Diameter of a Tree
Given a tree
T
with non-negative weight, find the diameter of the tree.
The diameter of a tree is the maximum distance between two nodes in a tree.
Input
n
s
1
t
1
w
1
s
2
t
2
w
2
:
s
n-1
t
n-1
w
n-1
The first line consists of an integer
n
which represents the number of nodes in the tree. Every node has a unique ID from 0 to
n
-1 respectively.
In the following
n
-1 lines, edges of the tree are given.
s
i
and
t
i
represent end-points of the
i
-th edge (undirected) and
w
i
represents the weight (distance) of the
i
-th edge.
Output
Print the diameter of the tree in a line.
Constraints
1 ≤
n
≤ 100,000
0 ≤
w
i
≤ 1,000
Sample Input 1
4
0 1 2
1 2 1
1 3 3
Sample Output 1
5
Sample Input 2
4
0 1 1
1 2 2
2 3 4
Sample Output 2
7

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Node
{
    vector<pair<int, int>> children; // destination node, length
    int length;
};

pair<int, int> theFurthest(const vector<Node> &nodes, int current, vector<bool> &searched)
{
    int furthestDestination = current;
    int furthestLength = 0;
    for (auto [dest, length] : nodes[current].children)
    {
        if (searched[dest])
            continue;
        searched[dest] = true;
        auto [tmpDest, tmpLength] = theFurthest(nodes, dest, searched);
        if (furthestLength < tmpLength + length)
        {
            furthestDestination = tmpDest;
            furthestLength = tmpLength + length;
        }
    }
    return pair<int, int>(furthestDestination, furthestLength);
}

int getInitialFurthestDestination(const vector<Node> &nodes)
{
    vector<bool> searched(nodes.size());
    searched[0] = true;
    auto [dest, length] = theFurthest(nodes, 0, searched);
    return dest;
}

int getFurthestLength(const vector<Node> &nodes, int startingNode)
{
    vector<bool> searched(nodes.size());
    searched[startingNode] = true;
    auto [dest, length] = theFurthest(nodes, startingNode, searched);
    return length;
}

int main()
{
    int n;
    cin >> n;

    vector<Node> nodes(n);
    for (int i = 0; i < n - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;
        nodes[s].children.emplace_back(t, w);
        nodes[t].children.emplace_back(s, w);
    }

    int initialFurthestDestination = getInitialFurthestDestination(nodes);
    cout << getFurthestLength(nodes, initialFurthestDestination) << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 16908
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Node
{
    vector<pair<int, int>> children; // destination node, length
    int length;
};

pair<int, int> theFurthest(const vector<Node> &nodes, int current, vector<bool> &searched)
{
    int furthestDestination = current;
    int furthestLength = 0;
    for (auto [dest, length] : nodes[current].children)
    {
        if (searched[dest])
            continue;
        searched[dest] = true;
        auto [tmpDest, tmpLength] = theFurthest(nodes, dest, searched);
        if (furthestLength < tmpLength + length)
        {
            furthestDestination = tmpDest;
            furthestLength = tmpLength + length;
        }
    }
    return pair<int, int>(furthestDestination, furthestLength);
}

int main()
{
    int n;
    cin >> n;

    vector<Node> nodes(n);
    for (int i = 0; i < n - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;
        nodes[s].children.emplace_back(t, w);
        nodes[t].children.emplace_back(s, w);
    }

    int initialFurthestDestination = 0;
    {
        vector<bool> searched(n);
        searched[0] = true;
        auto [dest, length] = theFurthest(nodes, 0, searched);
        initialFurthestDestination = dest;
    }

    int diameter = 0;
    {
        vector<bool> searched(n);
        searched[initialFurthestDestination] = true;
        auto [dest, length] = theFurthest(nodes, initialFurthestDestination, searched);
        diameter = length;
    }

    cout << diameter << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 17300
final_rank: 6

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Node
{
    vector<pair<int, int>> children; // destination node, length
    int length;
};

pair<int, int> theFurthest(const vector<Node> &nodes, int current, vector<bool> &searched)
{
    int furthestDestination = current;
    int furthestLength = 0;
    for (auto [dest, length] : nodes[current].children)
    {
        if (searched[dest])
            continue;
        searched[dest] = true;
        auto [tmpDest, tmpLength] = theFurthest(nodes, dest, searched);
        if (furthestLength < tmpLength + length)
        {
            furthestDestination = tmpDest;
            furthestLength = tmpLength + length;
        }
    }
    return pair<int, int>(furthestDestination, furthestLength);
}

int main()
{
    int n;
    cin >> n;

    vector<Node> nodes(n);
    for (int i = 0; i < n - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;
        nodes[s].children.push_back(pair<int, int>(t, w));
        nodes[t].children.push_back(pair<int, int>(s, w));
    }

    int initialFurthestDestination = 0;
    int initialFurthestLength = 0;
    {
        vector<bool> searched(n);
        searched[0] = true;
        auto [dest, length] = theFurthest(nodes, 0, searched);
        initialFurthestDestination = dest;
        initialFurthestLength = length;
    }

    int diameter = 0;
    {
        vector<bool> searched(n);
        searched[initialFurthestDestination] = true;
        auto [dest, length] = theFurthest(nodes, initialFurthestDestination, searched);
        diameter = length;
    }

    cout << diameter << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 17080
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Node
{
    vector<pair<int, int>> children; // destination node, length
    int length;
};

pair<int, int> theFurthest(const vector<Node> &nodes, int current, vector<bool> &searched)
{
    int maxLengthDestination = current;
    int maxLength = 0;
    for (auto [dest, length] : nodes[current].children)
    {
        if (searched[dest])
            continue;
        searched[dest] = true;
        auto [tmpDest, tmpLength] = theFurthest(nodes, dest, searched);
        if (maxLength < tmpLength + length)
        {
            maxLengthDestination = tmpDest;
            maxLength = tmpLength + length;
        }
    }
    return pair<int, int>(maxLengthDestination, maxLength);
}

int main()
{
    int n;
    cin >> n;

    vector<Node> nodes(n);
    for (int i = 0; i < n - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;
        nodes[s].children.push_back(pair<int, int>(t, w));
        nodes[t].children.push_back(pair<int, int>(s, w));
    }

    int initialMaxDestination = 0;
    int initialMaxLength = 0;
    {
        vector<bool> searched(n);
        searched[0] = true;
        auto [dest, length] = theFurthest(nodes, 0, searched);
        initialMaxDestination = dest;
        initialMaxLength = length;
    }

    int diameter = 0;
    {
        vector<bool> searched(n);
        searched[initialMaxDestination] = true;
        auto [dest, length] = theFurthest(nodes, initialMaxDestination, searched);
        diameter = length;
    }

    cout << diameter << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 16992
final_rank: 11

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Node
{
    vector<pair<int, int>> children; // destination node, length
    int length;
};

pair<int, int> theFurthest(const vector<Node> &nodes, int current, vector<bool> &searched)
{
    int biggest = 0;
    int biggestDestination = current;
    for (auto [dest, length] : nodes[current].children)
    {
        if (searched[dest])
            continue;
        searched[dest] = true;
        auto [tmpDest, tmpLength] = theFurthest(nodes, dest, searched);
        if (biggest < tmpLength + length)
        {
            biggestDestination = tmpDest;
            biggest = tmpLength + length;
        }
    }
    return pair<int, int>(biggestDestination, biggest);
}

int main()
{
    int n;
    cin >> n;

    vector<Node> nodes(n);
    for (int i = 0; i < n - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;
        nodes[s].children.push_back(pair<int, int>(t, w));
        nodes[t].children.push_back(pair<int, int>(s, w));
    }

    int firstBiggestDestination = 0;
    int firstBiggest = 0;
    {
        vector<bool> searched(n);
        searched[0] = true;
        auto [dest, length] = theFurthest(nodes, 0, searched);
        firstBiggestDestination = dest;
        firstBiggest = length;
    }

    int secondBiggestDestination = 0;
    int secondBiggest = 0;
    {
        vector<bool> searched(n);
        searched[firstBiggestDestination] = true;
        auto [dest, length] = theFurthest(nodes, firstBiggestDestination, searched);
        secondBiggestDestination = dest;
        secondBiggest = length;
    }

    cout << secondBiggest << endl;
}

// 0 から一番遠い点を見つけて、その点から一番遠い点が直径
accuracy: 1
time_ms: 50
memory_kb: 17304
final_rank: 13

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Node
{
    vector<pair<int, int>> children; // destination node, length
    int length;
    bool searched = false;
};

int maxDiameter(vector<Node> &nodes, int current, int &diameter)
{
    // 節点から伸びる辺で重みが大きい上位2つを記録する
    int firstBiggest = 0;
    int secondBiggest = 0;

    nodes[current].searched = true;
    // 節点から伸びる辺ごとの重みを調べる
    for (auto [dest, length] : nodes[current].children)
    {
        if (nodes[dest].searched)
            continue;
        // 節点から伸びた辺の重みとその先の点の重みの和
        int num = length + maxDiameter(nodes, dest, diameter);
        if (firstBiggest < num)
        {
            secondBiggest = firstBiggest;
            firstBiggest = num;
        }
        else if (secondBiggest < num)
            secondBiggest = num;
    }
    diameter = max(diameter, firstBiggest + secondBiggest);
    return firstBiggest;
}

int main()
{
    int n;
    cin >> n;

    vector<Node> nodes(n);
    for (int i = 0; i < n - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;
        nodes[s].children.push_back(pair<int, int>(t, w));
        nodes[t].children.push_back(pair<int, int>(s, w));
    }

    int diameter = 0;
    maxDiameter(nodes, 0, diameter);
    cout << diameter << endl;
}

// 各節点で二番目までの大きさの和が最大か確認する
accuracy: 1
time_ms: 40
memory_kb: 17164
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Node
{
    vector<pair<int, int>> children; // destination node, length
    int length;
};

int maxDiameter(const vector<Node> &nodes, int current, int &diameter)
{
    // 節点から伸びる辺で重みが大きい上位2つを記録する
    int firstBiggest = 0;
    int secondBiggest = 0;

    // 節点から伸びる辺ごとの重みを調べる
    for (auto [dest, length] : nodes[current].children)
    {
        // 節点から伸びた辺の重みとその先の点の重みの和
        int num = length + maxDiameter(nodes, dest, diameter);
        if (firstBiggest < num)
        {
            secondBiggest = firstBiggest;
            firstBiggest = num;
        }
        else if (secondBiggest < num)
            secondBiggest = num;
    }
    diameter = max(diameter, firstBiggest + secondBiggest);
    return firstBiggest;
}

int main()
{
    int n;
    cin >> n;

    vector<Node> nodes(n);
    for (int i = 0; i < n - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;
        nodes[s].children.push_back(pair<int, int>(t, w));
    }

    int diameter = 0;
    maxDiameter(nodes, 0, diameter);
    cout << diameter << endl;
}

// 各節点で二番目までの大きさの和が最大か確認する
accuracy: 1
time_ms: 40
memory_kb: 17304
final_rank: 7

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Node
{
    vector<pair<int, int>> children; // destination node, length
    int length;
};

int maxDiameter(vector<Node> &nodes, int current, int &diameter)
{
    // 節点から伸びる辺で重みが大きい上位2つを記録する
    int firstBiggest = 0;
    int secondBiggest = 0;

    // 節点から伸びる辺ごとの重みを調べる
    for (pair<int, int> &child : nodes[current].children)
    {
        // 節点から伸びた辺の重みとその先の点の重みの和
        int num = child.second + maxDiameter(nodes, child.first, diameter);
        if (firstBiggest < num)
        {
            secondBiggest = firstBiggest;
            firstBiggest = num;
        }
        else if (secondBiggest < num)
            secondBiggest = num;
    }
    diameter = max(diameter, firstBiggest + secondBiggest);
    return firstBiggest;
}

int main()
{
    int n;
    cin >> n;

    vector<Node> nodes(n);
    for (int i = 0; i < n - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;
        nodes[s].children.push_back(pair<int, int>(t, w));
    }

    int diameter = 0;
    maxDiameter(nodes, 0, diameter);
    cout << diameter << endl;
}

// 中心の点をどこにするかによって直径は変わってくる
// 中心は s, 各中心から長い距離を二つ探す(親も可)
// 中間の点は決まっている
// 各親で二番目までの大きさの和が最大か確認する
accuracy: 1
time_ms: 40
memory_kb: 16988
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 中心の点をどこにするかによって直径は変わってくる
// 中心は s, 各中心から長い距離を二つ探す(親も可)
// 中間の点は決まっている
// 各親で二番目までの大きさの和が最大か確認する

struct Node
{
    vector<pair<int, int>> children; // destination node, length
    int length;
};

int maxDiameter(vector<Node> &nodes, int current, int &diameter)
{
    int firstBiggest = 0;
    int secondBiggest = 0;
    for (pair<int, int> &child : nodes[current].children)
    {
        int num = maxDiameter(nodes, child.first, diameter) + child.second;
        if (firstBiggest < num)
        {
            secondBiggest = firstBiggest;
            firstBiggest = num;
        }
        else if (secondBiggest < num)
            secondBiggest = num;
    }
    diameter = max(diameter, firstBiggest + secondBiggest);
    return firstBiggest;
}

int main()
{
    int n;
    cin >> n;

    vector<Node> nodes(n);
    for (int i = 0; i < n - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;
        nodes[s].children.push_back(pair<int, int>(t, w));
    }

    int diameter = 0;
    maxDiameter(nodes, 0, diameter);
    cout << diameter << endl;
}

/*
 0 1
 0 2
 の場合は
 1 0 2 の距離
*/
accuracy: 1
time_ms: 40
memory_kb: 15312
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;

struct Edge
{
    size_t t; // 端点
    size_t w; // 重み
    Edge(size_t t, size_t w) : t(t), w(w) {}
};

// 幅優先探索（再帰）
void breadth_first_search(int u, int distance, const vector<list<Edge>> &A, vector<int> &d)
{
    if (d[u] != -1 && distance >= d[u])
    {
        return;
    }

    d[u] = distance;

    for (auto e : A[u])
    {
        breadth_first_search(e.t, distance + e.w, A, d);
    }
}

int main()
{
    size_t n; // 頂点数
    cin >> n;
    vector<list<Edge>> A(n); // 隣接行列

    for (size_t i = 0; i < n - 1; ++i)
    {
        int s, t, w;
        cin >> s >> t >> w;

        A[s].push_back(Edge(t, w));
        A[t].push_back(Edge(s, w));
    }

    vector<int> d0(n, -1); // ノード0からの最短距離
    breadth_first_search(0, 0, A, d0);
    auto iter = max_element(d0.begin(), d0.end()); // ノード0から最遠点
    size_t index = distance(d0.begin(), iter);     // ノード0から最遠点index

    vector<int> di(n, -1); // ノードindexからの最短距離
    breadth_first_search(index, 0, A, di);
    auto iter_max = max_element(di.begin(), di.end()); // ノードindexから最遠点

    // 結果を出力
    cout << *iter_max << endl;

    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 20188
final_rank: 15

code_snippet: //任求一个点到达的最远点，那个最远点的最长路径就是最远距离也就是树的直径
#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int MAX=100000+2;
int n;
int dis=0;
int far;
vector<pair<int,int>> A[MAX];
//答案做法，class类居然也可以放在vector里！！！
//求最远距离和最远点，我们只需要求一个点到所有点的所有距离然后比较就行了，一个dps或者bps就可以了；
class Edge{
    public:
    int s,w;
    Edge(){}
    Edge(int s,int w):s(s),w(w){}
};
vector<Edge> B[MAX];
int d[MAX];//既充当记录距离又负责判断有没有访问过
void bps(int l){
    for(int i=0;i<n;i++){
        d[i]=INF;
    }
    queue<int> O;
    O.push(l);
    d[l]=0;
    while(!O.empty()){
        int u=O.front();
        O.pop();
        for(int i=0;i<(int)B[u].size();i++){
            Edge m=B[u][i];
            if(d[m.s]==INF){//防止走回头路回到父结点，类似于dps关于父节点的判断
                d[m.s]=m.w+d[u];
                O.push(m.s);
            }
        }
    }
}
void solve(){
    bps(0);
    int maxv=0;
    int tgt=0;
    for(int i=0;i<n;i++){
        /*if(d[i]!=INF){

        }可以用下面的continue换掉*/
        if(d[i]==INF)continue;
        if(d[i]>maxv){
            maxv=d[i];
            tgt=i;//找到最远点
        }
    }
    bps(tgt);
    maxv=0;
    for(int i=0;i<n;i++){
        if(d[i]!=INF){
            maxv=max(maxv,d[i]);
        }
    }
    printf("%d",maxv);
}//答案的做法至此
void searchmax(int a,int m,int c){
    if(c>dis){
        dis=c;
        far=a;
    }
    for(int i=0;i<(int)A[a].size();i++){
        int v=A[a][i].first;
        int g=A[a][i].second;
        if(v!=m){
            searchmax(v,a,c+g);
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<(n-1);i++){
        int s,t,w;
        scanf("%d %d %d",&s,&t,&w);
        A[s].push_back(make_pair(t,w));
        A[t].push_back(make_pair(s,w));
    }
    searchmax(0,-1,0);
    dis=0;
    searchmax(far,-1,0);
    printf("%d\n",dis);
    return 0;
}
//答案做法，class类居然也可以放在vector里！！！
accuracy: 1
time_ms: 20
memory_kb: 15312
final_rank: 1

code_snippet: #define _GLGBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;

struct Edge
{
    int to;
    int weight;
};

struct DP
{
    int max_dist;
    int max_dist_vertex;

    bool operator<(const DP &other) const
    {
        if (max_dist != other.max_dist)
            return max_dist < other.max_dist;

        return max_dist_vertex < other.max_dist_vertex;
    }
};

int N, ID = 0, invalid_vertex = -1;
vector<vector<Edge>> G;
vector<vector<DP>> dp;
vector<DP> ans;
vector<int> to_parent_edge_weights;

DP dfs(int root, int parent)
{
    int out_degree_of_root = static_cast<int>(G.at(root).size());
    DP max_dp_of_subtree{ID, root};

    dp.at(root) = vector<DP>(out_degree_of_root, DP{ID, invalid_vertex});

    for (int i = 0; i < out_degree_of_root; i++)
    {
        int adjacent = G.at(root).at(i).to;

        if (adjacent == parent) {
            to_parent_edge_weights.at(root) = G.at(root).at(i).weight;
            continue;
        }

        dp.at(root).at(i) = dfs(adjacent, root);

        if (max_dp_of_subtree < dp.at(root).at(i))
            max_dp_of_subtree = dp.at(root).at(i);
    }

    return DP{
        max_dp_of_subtree.max_dist + to_parent_edge_weights.at(root),
        max_dp_of_subtree.max_dist_vertex,
    };
}

void dfs_reroot(int root, DP parent_subtree_dp_info, int parent)
{
    int out_degree_of_root = static_cast<int>(G.at(root).size());

    for (int i = 0; i < out_degree_of_root; i++)
        if (G.at(root).at(i).to == parent) {
            dp.at(root).at(i) = parent_subtree_dp_info;
            break;
        }

    vector<DP> dp_prefix(out_degree_of_root + 1, DP{ID, invalid_vertex}), dp_suffix(out_degree_of_root + 1, DP{ID, invalid_vertex});

    for (int i = 0; i < out_degree_of_root; i++)
    {
        if (dp_prefix.at(i) < dp.at(root).at(i))
            dp_prefix.at(i + 1) = dp.at(root).at(i);
        else
            dp_prefix.at(i + 1) = dp_prefix.at(i);
    }

    for (int i = out_degree_of_root - 1; i >= 0; i--)
    {
        if (dp_suffix.at(i + 1) < dp.at(root).at(i))
            dp_suffix.at(i) = dp.at(root).at(i);
        else
            dp_suffix.at(i) = dp_suffix.at(i + 1);
    }

    ans.at(root) = DP{
        dp_prefix.at(out_degree_of_root).max_dist,
        dp_prefix.at(out_degree_of_root).max_dist_vertex,
    };

    for (int i = 0; i < out_degree_of_root; i++)
    {
        int adjacent = G.at(root).at(i).to;

        if (adjacent == parent)
            continue;

        DP max_dp_info;

        if (dp_prefix.at(i) < dp_suffix.at(i + 1))
            max_dp_info = dp_suffix.at(i + 1);
        else
            max_dp_info = dp_prefix.at(i);

        max_dp_info.max_dist += to_parent_edge_weights.at(adjacent);

        if (out_degree_of_root == 1)
            max_dp_info.max_dist_vertex = root;

        dfs_reroot(adjacent, max_dp_info, root);
    }
}

int main()
{
    cin >> N;

    G.resize(N);
    dp.resize(N);
    ans.resize(N, DP{ID, invalid_vertex});
    to_parent_edge_weights.resize(N);

    for (int i = 1; i <= N - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;

        G.at(s).push_back(Edge{t, w});
        G.at(t).push_back(Edge{s, w});
    }

    dfs(0, -1);
    dfs_reroot(0, DP{ID, -1}, -1);

    int tree_diameter = 0;

    for (int i = 0; i < N; i++)
        tree_diameter = max(tree_diameter, ans.at(i).max_dist);

    cout << tree_diameter << '\n';

    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 32392
final_rank: 19

code_snippet: #define _GLGBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;

struct Edge
{
    int to;
    int weight;
};

struct DP
{
    int max_dist;
    int max_dist_vertex;

    bool operator<(const DP &other) const
    {
        if (max_dist != other.max_dist)
            return max_dist < other.max_dist;

        return max_dist_vertex < other.max_dist_vertex;
    }
};

int N, ID = 0, invalid_vertex = -1;
vector<vector<Edge>> G;
vector<vector<DP>> dp;
vector<DP> ans;
vector<int> to_parent_edge_weights;

DP dfs(int root, int parent)
{
    int out_degree_of_root = static_cast<int>(G.at(root).size()), to_parent_edge_weight;
    DP max_dp_of_subtree{ID, root};

    dp.at(root) = vector<DP>(out_degree_of_root, DP{ID, invalid_vertex});

    for (int i = 0; i < out_degree_of_root; i++)
    {
        int adjacent = G.at(root).at(i).to;

        if (adjacent == parent) {
            to_parent_edge_weights.at(root) = G.at(root).at(i).weight;
            continue;
        }

        dp.at(root).at(i) = dfs(adjacent, root);

        if (max_dp_of_subtree < dp.at(root).at(i))
            max_dp_of_subtree = dp.at(root).at(i);
    }

    return DP{
        max_dp_of_subtree.max_dist + to_parent_edge_weights.at(root),
        max_dp_of_subtree.max_dist_vertex,
    };
}

void dfs_reroot(int root, DP parent_subtree_dp_info, int parent)
{
    int out_degree_of_root = static_cast<int>(G.at(root).size()), to_parent_edge_weight;

    for (int i = 0; i < out_degree_of_root; i++)
        if (G.at(root).at(i).to == parent) {
            dp.at(root).at(i) = parent_subtree_dp_info;
            break;
        }

    vector<DP> dp_prefix(out_degree_of_root + 1, DP{ID, invalid_vertex}), dp_suffix(out_degree_of_root + 1, DP{ID, invalid_vertex});

    for (int i = 0; i < out_degree_of_root; i++)
    {
        if (dp_prefix.at(i) < dp.at(root).at(i))
            dp_prefix.at(i + 1) = dp.at(root).at(i);
        else
            dp_prefix.at(i + 1) = dp_prefix.at(i);
    }

    for (int i = out_degree_of_root - 1; i >= 0; i--)
    {
        if (dp_suffix.at(i + 1) < dp.at(root).at(i))
            dp_suffix.at(i) = dp.at(root).at(i);
        else
            dp_suffix.at(i) = dp_suffix.at(i + 1);
    }

    ans.at(root) = DP{
        dp_prefix.at(out_degree_of_root).max_dist,
        dp_prefix.at(out_degree_of_root).max_dist_vertex,
    };

    for (int i = 0; i < out_degree_of_root; i++)
    {
        int adjacent = G.at(root).at(i).to;

        if (adjacent == parent)
            continue;

        DP max_dp_info;

        if (dp_prefix.at(i) < dp_suffix.at(i + 1))
            max_dp_info = dp_suffix.at(i + 1);
        else
            max_dp_info = dp_prefix.at(i);

        max_dp_info.max_dist += to_parent_edge_weights.at(adjacent);

        if (out_degree_of_root == 1)
            max_dp_info.max_dist_vertex = root;

        dfs_reroot(adjacent, max_dp_info, root);
    }
}

int main()
{
    cin >> N;

    G.resize(N);
    dp.resize(N);
    ans.resize(N, DP{ID, invalid_vertex});
    to_parent_edge_weights.resize(N);

    for (int i = 1; i <= N - 1; i++)
    {
        int s, t, w;
        cin >> s >> t >> w;

        G.at(s).push_back(Edge{t, w});
        G.at(t).push_back(Edge{s, w});
    }

    dfs(0, -1);
    dfs_reroot(0, DP{ID, -1}, -1);

    int tree_diameter = 0;

    for (int i = 0; i < N; i++)
        tree_diameter = max(tree_diameter, ans.at(i).max_dist);

    cout << tree_diameter << '\n';

    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 32196
final_rank: 17

code_snippet: #include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <list>
#include <queue>

using Path = std::pair<int, int>; // 経路。頂点0から頂点番号secondまでの距離はfirst
using Edge = std::pair<int, int>; // 辺。ある点から頂点番号firstまでの距離はsecond
using Graph = std::vector<std::list<Edge>>;
std::vector<int> sssp(const Graph& G, int index) {
    int n = G.size();
    std::vector<int> D(n, -1); // 始点から各頂点までの距離、負数は距離未確定

    // 始点からの距離が近い順に、距離・頂点番号ペアを保持する
    std::priority_queue<Path, std::deque<Path>, std::greater<Path>> paths;
    paths.emplace(0, index); // 始点から始点までの距離は0

    int count = 0;
    while(paths.empty() == false) {
        // 始点からの最も近い点を得る
        const auto [d, u] = paths.top(); paths.pop();
        // その点へ接続する、接続済みなら飛ばす
        if (D[u] >= 0) continue;
        D[u] = d;
        if (++count == n) break;

        // 新たな頂点に隣接する頂点の経路を追加する
        for (const auto& [v, c] : G[u]) {
            if (D[v] >= 0) continue;
            paths.emplace(D[u] + c, v);
        }
    }
    return D;
}

int main() {
    int n;
    std::cin >> n;
    Graph g(n);
    for (int i = 0; i < n - 1; ++i) {
        int s, t, w;
        std::cin >> s >> t >> w;
        g[s].push_back({t, w});
        g[t].push_back({s, w});
    }

    auto d = sssp(g, 0);
    auto m = std::distance(d.begin(), std::max_element(d.begin(), d.end()));
    d = sssp(g, m);
    std::cout << *std::max_element(d.begin(), d.end()) << std::endl;
}
accuracy: 1
time_ms: 80
memory_kb: 12584
final_rank: 18

code_snippet: #include <algorithm>
#include <iostream>
#include <iomanip>
#include <limits.h>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <stack>
#include <complex>
#include <array>
#include <cassert>
#include <random>

using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(A) A.begin(), A.end()
#define debug(var) cout << #var << " = " << var << endl;
typedef long long ll;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p)
{
    os << "(" << p.first << "," << p.second << ")";
    return os;
}

template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p)
{
    is >> p.first >> p.second;
    return is;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v)
{
    for (int i = 0; i < (int)v.size(); i++)
    {
        os << v[i] << (i + 1 != (int)v.size() ? " " : "");
    }
    return os;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<vector<T>> &v)
{
    for (int i = 0; i < (int)v.size(); i++)
    {
        os << v[i] << endl;
    }
    return os;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<vector<vector<T>>> &v)
{
    int n = v.size();
    int m = v[0].size();
    int p = v[0][0].size();
    rep(k, p)
    {
        os << "k = " << k << endl;
        rep(i, n)
        {
            rep(j, m)
            {
                os << v[i][j][k];
                if (j < m - 1)
                {
                    os << " ";
                }
                else
                {
                    os << endl;
                }
            }
        }
    }
    return os;
}

template <typename T>
istream &operator>>(istream &is, vector<T> &v)
{
    for (T &in : v)
        is >> in;
    return is;
}

template <typename T, typename S>
ostream &operator<<(ostream &os, map<T, S> &mp)
{
    for (auto &[key, val] : mp)
    {
        os << key << ":" << val << " ";
    }
    cout << endl;
    return os;
}

template <typename T>
ostream &operator<<(ostream &os, set<T> st)
{
    auto itr = st.begin();
    for (int i = 0; i < (int)st.size(); i++)
    {
        os << *itr << (i + 1 != (int)st.size() ? " " : "");
        itr++;
    }
    return os;
}

template <typename T>
ostream &operator<<(ostream &os, multiset<T> st)
{
    auto itr = st.begin();
    for (int i = 0; i < (int)st.size(); i++)
    {
        os << *itr << (i + 1 != (int)st.size() ? " " : "");
        itr++;
    }
    return os;
}

template <typename T>
ostream &operator<<(ostream &os, queue<T> q)
{
    while (q.size())
    {
        os << q.front() << " ";
        q.pop();
    }
    return os;
}

template <typename T>
ostream &operator<<(ostream &os, deque<T> q)
{
    while (q.size())
    {
        os << q.front() << " ";
        q.pop_front();
    }
    return os;
}

template <typename T>
ostream &operator<<(ostream &os, stack<T> st)
{
    while (st.size())
    {
        os << st.top() << " ";
        st.pop();
    }
    return os;
}

template <typename T>
ostream &operator<<(ostream &os, priority_queue<T> pq)
{
    while (pq.size())
    {
        os << pq.top() << " ";
        pq.pop();
    }
    return os;
}

template <typename T>
ostream &operator<<(ostream &os, priority_queue<T, vector<T>, greater<T>> mpq)
{
    while (mpq.size())
    {
        os << mpq.top() << " ";
        mpq.pop();
    }
    return os;
}
template <class E, class V, E (*merge)(E, E), E (*e)(), E (*put_edge)(V, int), V (*put_vertex)(E, int)>
struct RerootingDP {
    struct edge {
        int to, idx, xdi;
    };
    RerootingDP(int n_ = 0) : n(n_), inner_edge_id(0) {
        es.resize(2*n-2);
        start.resize(2*n-2);
        if (n == 1) es_build();
    }
    void add_edge(int u, int v, int idx, int xdi){
        start[inner_edge_id] = u;
        es[inner_edge_id] = {v,idx,xdi};
        inner_edge_id++;
        start[inner_edge_id] = v;
        es[inner_edge_id] = {u,xdi,idx};
        inner_edge_id++;
        if (inner_edge_id == 2*n-2){
            es_build();
        }
    }
    vector<V> build(int root_ = 0){
        root = root_;
        vector<V> subdp(n); subdp[0] = put_vertex(e(),0);
        outs.resize(n);
        vector<int> geta(n+1,0);
        for (int i = 0; i < n; i++) geta[i+1] = start[i+1] - start[i] - 1;
        geta[root+1]++;
        for (int i = 0; i < n; i++) geta[i+1] += geta[i];
        auto dfs = [&](auto sfs, int v, int f) -> void {
            E val = e();
            for (int i = start[v]; i < start[v+1]; i++){
                if (es[i].to == f){
                    swap(es[start[v+1]-1],es[i]);
                }
                if (es[i].to == f) continue;
                sfs(sfs,es[i].to,v);
                E nval = put_edge(subdp[es[i].to],es[i].idx);
                outs[geta[v]++] = nval;
                val = merge(val,nval);
            }
            subdp[v] = put_vertex(val, v);
        };
        dfs(dfs,root,-1);
        return subdp;
    }
    vector<V> reroot(){
        vector<E> reverse_edge(n);
        reverse_edge[root] = e();
        vector<V> answers(n);
        auto dfs = [&](auto sfs, int v) -> void {
            int le = outs_start(v);
            int ri = outs_start(v+1);
            int siz = ri - le;
            vector<E> rui(siz+1);
            rui[siz] = e();
            for (int i = siz-1; i >= 0; i--){
                rui[i] = merge(outs[le+i],rui[i+1]);
            }
            answers[v] = put_vertex(merge(rui[0],reverse_edge[v]),v);
            E lui = e();
            for (int i = 0; i < siz; i++){
                V rdp = put_vertex(merge(merge(lui,rui[i+1]),reverse_edge[v]),v);
                reverse_edge[es[start[v]+i].to] = put_edge(rdp,es[start[v]+i].xdi);
                lui = merge(lui,outs[le+i]);
                sfs(sfs,es[start[v]+i].to);
            }
        };
        dfs(dfs,root);
        return answers;
    }
    private:
    int n, root, inner_edge_id;
    vector<E> outs;
    vector<edge> es;
    vector<int> start;
    int outs_start(int v){
        int res = start[v] - v;
        if (root < v) res++;
        return res;
    }
    void es_build(){
        vector<edge> nes(2*n-2);
        vector<int> nstart(n+2,0);
        for (int i = 0; i < 2*n-2; i++) nstart[start[i]+2]++;
        for (int i = 0; i < n; i++) nstart[i+1] += nstart[i];
        for (int i = 0; i < 2*n-2; i++) nes[nstart[start[i]+1]++] = es[i];
        swap(es,nes);
        swap(start,nstart);
    }
};

// mint merge(mint a, mint b){
//     return a * b;
// }
// mint e(){
//     return mint(1);
// }
// mint put_edge(mint v, int i){
//     return v + 1;
// }
// mint put_vertex(mint e, int v){
//     return e;
// }

int merge(int a,int b){
    return max(a,b);
}
int e(){
    return 0;
}
int put_edge(int v,int i){
    return v+i;
}
int put_vertex(int e,int v){
    return e;
}
int main(){
    int n;
    cin >> n;
    RerootingDP<int,int,merge,e,put_edge,put_vertex> dp(n);
    rep(i,n-1){
        int u,v,w;
        cin >> u >> v >> w;
        dp.add_edge(u,v,w,w);
    }
    dp.build();
    int ans = INT_MIN;
    auto chmax = [](auto &a, const auto &b) {
        if(a<b){
            a=b;
            return true;
        }
        return false;
    };
    for(auto p:dp.reroot()){
        // debug(p);
        chmax(ans,p);
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 22412
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<(n);i++)
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define YES cout<<"Yes"<<endl
#define NO cout<<"No"<<endl
using ll=long long;
using pi=pair<ll,int>;
const int di[]={+1,-1,+0,+0};
const int dj[]={+0,+0,+1,-1};
const int INF=1e9;
//const ll INF=1e18;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<vector<pi>> G(n);
    rep(i, n-1) {
        int s, t;
        ll w;
        cin >> s >> t >> w;
        G[s].push_back({w, t});
        G[t].push_back({w, s});
    }
    vector<ll> dist(n, -1);
    auto dfs=[&](auto dfs, ll w, int v, int p=-1) -> void {
        dist[v]=w;
        for(auto [nw, nv]:G[v]) if(nv!=p) {
            nw+=w;
            dfs(dfs, nw, nv, v);
        }
    };
    dfs(dfs, 0LL, 0);
    ll mx=-1;
    int start=0;
    rep(i, n) {
        if(mx<dist[i]) {
            mx=dist[i];
            start=i;
        }
    }
    dfs(dfs, 0LL, start);
    ll diameter=-1;
    rep(i, n) diameter=max(diameter, dist[i]);
    cout << diameter << endl;

    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 18384
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <list>
#include <algorithm>

using Edge = std::pair<int, int>;            // 辺：向かう先, 重み
using Graph = std::vector<std::list<Edge>>;  // 隣接リスト

// x を根とする部分木で葉までの最大と直径を返す
// x が葉なら [0, 0] を返す
std::pair<int, int> dfs(const Graph& g, int x, int parent) {
    int diameter = 0;
    int max = 0;    // 葉までの重みの最大
    int sec = 0;    // 葉までの重みの2番目
    // xから伸びる辺のうち、子を探す
    for (auto [to, weight] : g[x]) {
        if (to == parent) continue; // 子を探す。親なら無視する
        auto [m, d] = dfs(g, to, x);
        // toを根とする部分木で大きい直径が見つかれば更新する
        diameter = std::max(diameter, d);
        // xからtoまでの重みにtoから葉までの重みを足す
        m += weight;
        // xからtoを辿って葉までの重みが大きいなら更新する
        if (m >= max) {
            sec = max;
            max = m;
        } else if (m > sec) {
            sec = m;
        }

    }
    // 子が1つなら、その子を辿って葉までの重みが直径候補
    // 子が2つ以上なら、1番目と2番目の重みの和が直径候補
    diameter = std::max(diameter, max + sec);

    return {max, diameter};
}
int main() {
    int n;
    std::cin >> n;
    Graph g(n);
    for (int i = 0; i < n - 1; ++i) {
        int s, t, w;
        std::cin >> s >> t >> w;
        g[s].push_back({t, w});
        g[t].push_back({s, w});
    }
    auto [_, d] = dfs(g, 0, 0);
    std::cout << d << std::endl;
}
accuracy: 1
time_ms: 50
memory_kb: 19376
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define vi vector<int>
#define vl vector<ll>
#define ov4(a, b, c, d, name, ...) name
#define rep3(i, a, b, c) for(ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for(ll i = (a)-1; i >= (b); i--)
#define fore(e, v) for(auto&& e : v)
#define all(a) begin(a), end(a)
#define si(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template<typename T, typename S> bool chmin(T& a, const S& b) { return a > b ? a = b, 1 : 0; }
template<typename T, typename S> bool chmax(T& a, const S& b) { return a < b ? a = b, 1 : 0; }

const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;

#define i128 __int128_t

struct _ {
   _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

vi par, dep, dist, q;
vector<bool> vis;

void dfs(vector<vector<pii>> &edges, int i, int b) {
    par[i] = b;
    vis[i] = true;
    q.push_back(i);
    for (auto [j, w] : edges[i]) {
        if (j == b) continue;
        dep[j] = dep[i] + 1;
        dist[j] = dist[i] + w;
        dfs(edges, j, i);
    }
}

int main() {
    int n;
    cin >> n;
    int m = n - 1;
    vector edges(n, vector<pii>{});
    rep(_, m) {
        int a, b, w;
        cin >> a >> b >> w;
        edges[a].push_back({b, w});
        edges[b].push_back({a, w});
    }

    par.resize(n); dep.resize(n); dist.resize(n); vis.resize(n);
    fill(all(dist), 0);
    fill(all(dep), 0);
    fill(all(vis), false);

    int B = 21;
    vector<vi> dub(n, vi(B, -1));

    auto up = [&](int i, int d) {
        rep(j, B) {
            if (d & 1) i = dub[i][j];
            d >>= 1;
        }
        return i;
    };
    auto lca = [&](int i, int j) {
        if (dep[i] < dep[j]) swap(i, j);
        i = up(i, dep[i] - dep[j]);
        if (i == j) return i;
        per(k, B, 0) if (dub[i][k] != dub[j][k]) {
            i = dub[i][k]; j = dub[j][k];
        }
        return par[i];
    };
    auto dis = [&](int i, int j) {
        int l = lca(i, j);
        return dist[i] + dist[j] - 2 * dist[l];
    };

    vl v{};

    rep(i, n) {
        if (vis[i]) continue;
        q.resize(0);
        dfs(edges, i, -1);

        fore(j, q) {
            dub[j][0] = par[j];
        }
        rep(j, B - 1) fore(k, q) if (dub[k][j] != -1) {
            dub[k][j + 1] = dub[dub[k][j]][j];
        }
        
        int l = i, mi = i;
        fore(j, q) if (dis(l, mi) < dis(l, j)) mi = j;
        l = mi;
        int r = i;
        fore(j, q) if (dis(l, r) < dis(l, j)) r = j;
        int c = i, mx = INF;
        fore(j, q) if (mx > dis(l, j) + dis(r, j)) c = j, mx = dis(l, j) + dis(r, j);
        v.push_back(mx);
    }

    cout << v[0] << endl; 
}
accuracy: 1
time_ms: 40
memory_kb: 30124
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i=0; i<n; i++)

struct Edge {
    int to, cost;
    Edge() = default;
    Edge(int to, int cost) : to(to), cost(cost) {}
};

int n;
vector<vector<Edge>> to;

vector<int> bfs(int s) {
    queue<int> q;
    vector<bool> visited(n);
    vector<int> length(n);
    int res = -1;

    q.push(s);
    visited[s] = true;
    length[s] = 0;
    while (!q.empty()) {
        int x = q.front(); q.pop();
        visited[x] = true;
        for (Edge e : to[x]) {
            if (visited[e.to]) continue;
            length[e.to] = length[x] + e.cost;
            q.push(e.to);
        }
    }

    return length;
}

int main()
{
    cin >> n;
    to.resize(n);
    rep(i,n-1) {
        int s, t, w;
        cin >> s >> t >> w;
        to[s].emplace_back(t,w);
        to[t].emplace_back(s,w);
    }

    vector<int> length = bfs(0);
    int x = -1, y = -1, max = -1;
    rep(i,n) {
        if (length[i] > max) {
            x = i;
            max = length[i];
        }
    }

    max = -1;
    length = bfs(x);
    rep(i,n) {
        if (length[i] > max) {
            y = i;
            max = length[i];
        }
    }

    cout << length[y] << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 10088
final_rank: 8

code_snippet: // # pragma GCC target("avx2")
// # pragma GCC optimize("O3")
// # pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;

// #include <boost/multiprecision/cpp_int.hpp>
// using namespace boost::multiprecision;

#define ll long long
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define vi vector<int>
#define vl vector<ll>
#define vd vector<double>
#define vb vector<bool>
#define vs vector<string>
#define vc vector<char>
#define ull unsigned long long
#define chmax(a,b) a=max(a,b)
#define chmin(a,b) a=min(a,b)



ll inf=(1ll<<60);
// const double PI=3.1415926535897932384626433832795028841971;


// ll rui(ll a,ll b){
//     if(b==0)return 1;
//     if(b%2==1) return a*rui(a*a,b/2);
//     return rui(a*a,b/2);
// }

// ll kai(ll n){
//     if(n==0)return 1;
//     return n*kai(n-1);
// }

// using mint = modint998244353;//static_modint<998244353>
// using mint = modint1000000007;//static_modint<1000000007>
// using mint = modint;//mint::set_mod(mod);


// ll const mod=1000000007ll;
// ll const mod=998244353ll;
// ll modrui(ll a,ll b,ll mod){
//     a%=mod;
//     if(b==0)return 1;
//     if(b%2==1) return a*modrui(a*a%mod,b/2,mod)%mod;
//     return modrui(a*a%mod,b/2,mod)%mod;
// }

// ll inv(ll x){
//     x%=mod;
//     return modrui(x,mod-2);
// }

// ll modkai(ll n){
//     ll ret=1;
//     rep(i,n){
//         ret*=(i+1)%mod;
//         ret%=mod;
//     }
//     return ret;
// }


// void incr(vl &v,ll n){//　n進法
//     ll k=v.size();
//     v[k-1]++;
//     ll now=k-1;
//     while (v[now]>=n)
//     {
//         v[now]=0;
//         if(now==0)break;
//         v[now-1]++;
//         now--;
//     }
//     return;
// }



vl dist(1<<17);
ll ans=0;

void dfs(vector<vector<vl>> const&g,ll x,ll p){
    for(auto &to:g[x]){
        if(to[0]==p)continue;
        dfs(g,to[0],x);
        chmax(dist[x],dist[to[0]]+to[1]);
    }
}

void dfs2(vector<vector<vl>> const&g,ll x,ll p,ll dp){
    vector<vl> d={{0,-1},{0,-2}};
    for(auto &to:g[x]){
        if(to[0]==p){
            d.push_back({dp+to[1],p});
        }
        else{
            d.push_back({dist[to[0]]+to[1],to[0]});
        }
    }
    sort(d.begin(),d.end());
    reverse(d.begin(),d.end());
    chmax(ans,d[0][0]+d[1][0]);
    for(auto &to:g[x]){
        if(to[0]==p)continue;
        if(d[0][1]!=to[0])dfs2(g,to[0],x,d[0][0]);
        else dfs2(g,to[0],x,d[1][0]);
    }
}



void solve(){
    ll n;
    cin >> n;
    vector<vector<vl>> g(n);
    rep(i,n-1){
        ll u,v,w;
        cin >> u >> v >> w;
        g[u].push_back({v,w});
        g[v].push_back({u,w});
    }
    dfs(g,0,-1);
    dfs2(g,0,-1,-1);

    
    cout << ans << endl;
}

int main(){
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    ll t=1;
    // cin >> t;
    while(t--)solve();
}
accuracy: 1
time_ms: 40
memory_kb: 62988
final_rank: 20