Problem:
Dungeion 3
You are a famous adventurer and have already conquered two dungeons. You have obtained a map of a new dungeon with several passages and treasure chests on it. The map shows the value of the treasures in each treasury.
You can enter the dungeon from any of the treasuries and escape the dungeon from any of the treasuries. During the time between entering and exiting, you can move several times through the passages between the treasuries to get the treasures of the treasuries you visited. According to the map, each passage can go in both directions, and you can reach any treasure house from any treasure house via one or more passages. However, once a passage is traversed, the second and subsequent passages can only be traversed in the same direction as the first. Treasures in the treasury can only be obtained the first time you visit it. At this time, we want to maximize the total value of the treasures we obtain.
Given the information on the map, write a program to find the maximum value of the sum of the values of the treasures that can be obtained from the time of entry to the time of escape. Assume that the treasuries are assigned numbers from 1 to $N$.
Input
The input is given in the following form.
$N$ $M$
$v_1$
$v_2$
:
$v_N$
$s_1$ $t_1$
$s_2$ $t_2$
:
$s_M$ $t_M$
In the first line, the number of treasuries $N$ ($2 \leq N \leq 10^5$) and the number of passages $M$ ($1 \leq M \leq 2 \times 10^5$) are given. In the following $N$ lines, the value $v_i$ ($1 \leq v_i \leq 1000$) of the treasure placed in the $i$-th treasury is given. In the following $M$ lines, the numbers $s_i$,$t_i$ ($1 \leq s_i,t_i \leq N,s_i \ne t_i$) of the treasure vaults connected to the two ends of each passage are given. No passage connecting the same treasury can be given more than once.
Output
Output the maximum value of the sum of the values of the treasures that can be obtained in a line.
Sample Input and Output
Sample Input
5 4
2
1
3
6
4
1 2
2 3
2 4
4 5
Sample Output
14

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif

struct LowLink {
    int N;
    // articulation: 関節点, bridge: 橋
    vector<int> order, low, articulation;
    vector<pair<int, int>> bridge;
    LowLink(const vector<vector<int>>& G) : N(G.size()), order(N, -1), low(N, -1) {
        for (int i = 0; i < N; i++) {
            if (order[i] == -1) dfs(G, i, -1, 0);
        }
    };

    void dfs(const vector<vector<int>>& G, int pos, int parent, int time) {
        order[pos] = low[pos] = time++;
        int child_cnt = 0;
        bool is_articulation = false, second = false;
        for (auto to : G[pos]) {
            if (order[to] == -1) {
                // to が未訪問の場合
                child_cnt++;
                dfs(G, to, pos, time);
                low[pos] = min(low[pos], low[to]);
                // order[pos] < low[to] ならば橋
                if (order[pos] < low[to]) bridge.emplace_back(minmax(pos, to));
                // 根以外で, order[pos] <= low[to] ならば関節点
                is_articulation |= parent != -1 && order[pos] <= low[to];
            } else if (to != parent || second) {
                // (pos, to) が後退辺 or 多重辺(後退辺)の場合
                low[pos] = min(low[pos], order[to]);
            } else {
                // to が 親の場合, もう一度 to を訪問したら (pos, to) は多重辺
                second = true;
            }
        }
        // 根かつ, 子が 2 つ以上ならば関節点
        is_articulation |= parent == -1 && child_cnt > 1;
        if (is_articulation) articulation.emplace_back(pos);
    };
};

struct TwoEdgeConnectedComponents {
    LowLink lowlink;
    vector<int> comp;  // 頂点[i] が属する 2 重辺連結成分の番号
    vector<vector<int>> groups, tree;
    int id;
    TwoEdgeConnectedComponents(const vector<vector<int>>& G) : lowlink(G), comp(G.size(), -1), id(0) {
        for (int i = 0; i < (int)G.size(); i++) {
            if (comp[i] == -1) dfs(G, i, -1);
        }
        groups.resize(id), tree.resize(id);
        for (int i = 0; i < (int)G.size(); i++) {
            groups[comp[i]].emplace_back(i);
        }
        for (auto [u, v] : lowlink.bridge) {
            tree[comp[u]].emplace_back(comp[v]);
            tree[comp[v]].emplace_back(comp[u]);
        }
    };

    void dfs(const vector<vector<int>>& G, int pos, int parent) {
        if (parent != -1 && lowlink.order[parent] >= lowlink.low[pos]) {
            // 根でないかつ, (pos, parent) が橋でない場合
            comp[pos] = comp[parent];
        } else {
            // 根または, (pos, parent) が橋の場合, 新しい２重辺連結成分を作る
            comp[pos] = id++;
        }
        for (auto to : G[pos]) {
            if (comp[to] != -1) continue;
            dfs(G, to, pos);
        }
    }
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<int> V(N);
    for (int i = 0; i < N; i++) cin >> V[i];
    vector<vector<int>> G(N);
    for (int i = 0; i < M; i++) {
        int s, t;
        cin >> s >> t, s--, t--;
        G[s].emplace_back(t);
        G[t].emplace_back(s);
    }

    // 二重辺連結成分内に入ると, その中にある財宝全てを取ることができて, 好きな頂点から抜けれる
    TwoEdgeConnectedComponents tecc(G);
    // 二重辺連結成分を縮約した木の頂点の重みを計算
    int N2 = ssize(tecc.tree);
    vector<int> V2(N2);
    for (int i = 0; i < N2; i++) {
        for (int u : tecc.groups[i]) V2[i] += V[u];
    }

    debug(tecc.groups, tecc.tree, V2);
    // 頂点重み付き木の最大 walk を計算
    vector<int> dist1(V2), dist2(V2);
    auto dfs = [&](auto&& self, int v, int p, int type) -> void {
        for (int u : tecc.tree[v]) {
            if (u == p) continue;
            if (type == 1) dist1[u] = max(dist1[u], dist1[v] + V2[u]);
            if (type == 2) dist2[u] = max(dist2[u], dist2[v] + V2[u]);
            self(self, u, v, type);
        }
    };
    dfs(dfs, 0, -1, 1);
    int r = max_element(dist1.begin(), dist1.end()) - dist1.begin();
    dfs(dfs, r, -1, 2);
    debug(dist1, dist2);
    cout << *max_element(dist2.begin(), dist2.end()) << '\n';
}
accuracy: 1
time_ms: 20
memory_kb: 34576
final_rank: 6

code_snippet: // AOJ #415
// Dungeon 3 2025.2.9

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {  // 整数の入力
	int n = 0, c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

char temp[100005];
string Cins() { // 文字列の入力　スペース以下の文字で入力終了
    char *s = temp;
	do *s = gc();
	while (*s++ > ' ');
	*(s-1) = 0;
    string input(temp); // 文字配列からstringを作成
    return input;
}

void Cout(ll n) { // 整数の表示（出力）
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}


struct Edge { int to, id; };
 
int n, m;
vector<vector<Edge>> adj;
vector<int> disc, low;
vector<bool> isBridge;
int timer = 0;
 
void dfs_bridges(int v, int parentEdge) {
    disc[v] = low[v] = timer++;
    for(auto &edge : adj[v]){
        int w = edge.to, id = edge.id;
        if(id == parentEdge) continue;
        if(disc[w] == -1) {
            dfs_bridges(w, id);
            low[v] = min(low[v], low[w]);
            if(low[w] > disc[v]) isBridge[id] = true;
        } else low[v] = min(low[v], disc[w]);
    }
}
 
int main() {
    n = Cin(), m = Cin();
    vector<int> treasure(n);
    for (int i = 0; i < n; i++) treasure[i] = Cin();
 
    vector<pair<int,int>> edgeList;
    edgeList.reserve(m);
    adj.assign(n, vector<Edge>());
    for (int i = 0; i < m; i++){
        int u = Cin()-1, v = Cin()-1;
        edgeList.push_back({u,v});
        adj[u].push_back({v, i});
        adj[v].push_back({u, i});
    }
 
    disc.assign(n, -1);
    low.assign(n, -1);
    isBridge.assign(m, false);
    timer = 0;
    for (int i = 0; i < n; i++){
        if(disc[i] == -1) dfs_bridges(i, -1);
    }
 
    vector<int> comp(n, -1);
    int compCount = 0;
    function<void(int,int)> dfs_comp = [&](int v, int c) {
        comp[v] = c;
        for(auto &edge : adj[v]) {
            int w = edge.to;
            if(comp[w] == -1 && !isBridge[edge.id])
                dfs_comp(w, c);
        }
    };
    for (int i = 0; i < n; i++){
        if(comp[i] == -1) dfs_comp(i, compCount++);
    }
 
    vector<ll> compWeight(compCount, 0);
    for (int i = 0; i < n; i++){
        compWeight[ comp[i] ] += treasure[i];
    }
 
    vector<vector<int>> tree(compCount);
    for (int i = 0; i < m; i++){
        if(isBridge[i]){
            int u = edgeList[i].first, v = edgeList[i].second;
            int cu = comp[u], cv = comp[v];
            tree[cu].push_back(cv);
            tree[cv].push_back(cu);
        }
    }
 
    if(compCount == 1){
        Cout(compWeight[0]);
        return 0;
    }
 
    ll bestDist = 0;
    int farthestNode = 0;
    vector<ll> dist(compCount, 0);
    function<void(int,int,ll)> dfs_tree = [&](int v, int parent, ll d) {
        dist[v] = d;
        if(d > bestDist) {
            bestDist = d;
            farthestNode = v;
        }
        for (int w : tree[v]) {
            if(w == parent) continue;
            dfs_tree(w, v, d + compWeight[w]);
        }
    };
 
    bestDist = 0;
    dfs_tree(0, -1, compWeight[0]);
    int start = farthestNode;
    bestDist = 0;
    fill(dist.begin(), dist.end(), 0);
    dfs_tree(start, -1, compWeight[start]);
    Cout(bestDist);
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 25612
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

#ifdef LOCAL
#include <debug_print.hpp>
#define debug(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (static_cast<void>(0))
#endif

struct LowLink {
    int N;
    // articulation: 関節点, bridge: 橋
    vector<int> order, low, articulation;
    vector<pair<int, int>> bridge;
    LowLink(const vector<vector<int>>& G) : N(G.size()), order(N, -1), low(N, -1) {
        for (int i = 0; i < N; i++) {
            if (order[i] == -1) dfs(G, i, -1, 0);
        }
    };

    void dfs(const vector<vector<int>>& G, int pos, int parent, int time) {
        order[pos] = low[pos] = time++;
        int child_cnt = 0;
        bool is_articulation = false, second = false;
        for (auto to : G[pos]) {
            if (order[to] == -1) {
                // to が未訪問の場合
                child_cnt++;
                dfs(G, to, pos, time);
                low[pos] = min(low[pos], low[to]);
                // order[pos] < low[to] ならば橋
                if (order[pos] < low[to]) bridge.emplace_back(minmax(pos, to));
                // 根以外で, order[pos] <= low[to] ならば関節点
                is_articulation |= parent != -1 && order[pos] <= low[to];
            } else if (to != parent || second) {
                // (pos, to) が後退辺 or 多重辺(後退辺)の場合
                low[pos] = min(low[pos], order[to]);
            } else {
                // to が 親の場合, もう一度 to を訪問したら (pos, to) は多重辺
                second = true;
            }
        }
        // 根かつ, 子が 2 つ以上ならば関節点
        is_articulation |= parent == -1 && child_cnt > 1;
        if (is_articulation) articulation.emplace_back(pos);
    };
};

struct TwoEdgeConnectedComponents {
    LowLink lowlink;
    vector<int> comp;  // 頂点[i] が属する 2 重辺連結成分の番号
    vector<vector<int>> groups, tree;
    int id;
    TwoEdgeConnectedComponents(const vector<vector<int>>& G) : lowlink(G), comp(G.size(), -1), id(0) {
        for (int i = 0; i < (int)G.size(); i++) {
            if (comp[i] == -1) dfs(G, i, -1);
        }
        groups.resize(id), tree.resize(id);
        for (int i = 0; i < (int)G.size(); i++) {
            groups[comp[i]].emplace_back(i);
        }
        for (auto [u, v] : lowlink.bridge) {
            tree[comp[u]].emplace_back(comp[v]);
            tree[comp[v]].emplace_back(comp[u]);
        }
    };

    void dfs(const vector<vector<int>>& G, int pos, int parent) {
        if (parent != -1 && lowlink.order[parent] >= lowlink.low[pos]) {
            // 根でないかつ, (pos, parent) が橋でない場合
            comp[pos] = comp[parent];
        } else {
            // 根または, (pos, parent) が橋の場合, 新しい２重辺連結成分を作る
            comp[pos] = id++;
        }
        for (auto to : G[pos]) {
            if (comp[to] != -1) continue;
            dfs(G, to, pos);
        }
    }
};


int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<int> V(N);
    for (int i = 0; i < N; i++) cin >> V[i];
    vector<vector<int>> G(N);
    for (int i = 0; i < M; i++) {
        int s, t; cin >> s >> t, s--, t--;
        G[s].emplace_back(t);
        G[t].emplace_back(s);
    }

    TwoEdgeConnectedComponents tecc(G);
    // 各 2 重辺連結成分の V の総和 W を求める
    vector<int> W(tecc.groups.size());
    for (int i = 0; i < N; i++) {
        W[tecc.comp[i]] += V[i];
    }

    // 二重頂点連結成分を縮約した木を作る
    auto G2 = tecc.tree;
    // 頂点 i の重みが W[i] の木の直径を求める
    auto tree_diameter = [&]() -> ll {
        int N = G2.size();
        auto dfs = [&](auto&& self, int pos, int parent) -> pair<ll, int> {
            pair<ll, int> res = {W[pos], pos};
            for (auto to : G2[pos]) {
                if (to == parent) continue;
                auto [d, v] = self(self, to, pos);
                if (res.first < d + W[pos]) res = {d + W[pos], v};
            }
            return res;
        };
        // 2 回 dfs
        auto [d, v] = dfs(dfs, 0, -1);
        auto [d2, v2] = dfs(dfs, v, -1);
        return d2;
    };
    cout << tree_diameter() << '\n';
}
accuracy: 1
time_ms: 30
memory_kb: 40392
final_rank: 14

code_snippet: #ifndef TEMPLATE
#define TEMPLATE 1

#pragma GCC optimize("O3,unroll-loops")

// #include <bits/stdc++.h>
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;

using pi = std::pair<int, int>;
using pl = std::pair<i64, i64>;
using pil = std::pair<int, i64>;
using pli = std::pair<i64, int>;

template <class T> constexpr T infty = 0;
template <> constexpr int infty<int> = (1 << 30) - 123;
template <> constexpr i64 infty<i64> = (1ll << 62) - (1ll << 31);
template <> constexpr i128 infty<i128> = i128(infty<i64>) * infty<i64>;
template <> constexpr u32 infty<u32> = infty<int>;
template <> constexpr u64 infty<u64> = infty<i64>;
template <> constexpr double infty<double> = infty<i64>;
template <> constexpr long double infty<long double> = infty<i64>;

constexpr int mod = 998244353;
constexpr int modu = 1e9 + 7;
constexpr long double PI = 3.14159265358979323846;

template <class T> using vc = std::vector<T>;
template <class T> using vvc = std::vector<vc<T>>;
template <class T> using vvvc = std::vector<vvc<T>>;
template <class T> using vvvvc = std::vector<vvvc<T>>;

template <class T> using pq = std::priority_queue<T>;
template <class T>
using pqi = std::priority_queue<T, std::vector<T>, std::greater<T>>;

namespace kk2 {

template <class T, class... Sizes>
auto make_vector(const T &init, int first, Sizes... sizes) {
    if constexpr (sizeof...(sizes) == 0) {
        return std::vector<T>(first, init);
    } else {
        return std::vector<decltype(make_vector(init, sizes...))>(
            first, make_vector(init, sizes...));
    }
}

template <class T, class U> void fill_all(std::vector<T> &v, const U &x) {
    std::fill(std::begin(v), std::end(v), T(x));
}

template <class T, class U>
void fill_all(std::vector<std::vector<T>> &v, const U &x) {
    for (auto &u : v) fill_all(u, x);
}

} // namespace kk2

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

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

#define rep1(a) for (i64 _ = 0; _ < (i64)(a); ++_)
#define rep2(i, a) for (i64 i = 0; i < (i64)(a); ++i)
#define rep3(i, a, b) for (i64 i = (a); i < (i64)(b); ++i)
#define repi2(i, a) for (i64 i = (a) - 1; i >= 0; --i)
#define repi3(i, a, b) for (i64 i = (a) - 1; i >= (i64)(b); --i)
#define overload3(a, b, c, d, ...) d
#define rep(...) overload3(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#define repi(...) overload3(__VA_ARGS__, repi3, repi2, rep1)(__VA_ARGS__)

#define fi first
#define se second
#define all(p) std::begin(p), std::end(p)

void YES(bool b = 1) {
    std::cout << (b ? "YES" : "NO") << '\n';
}

void NO(bool b = 1) {
    std::cout << (b ? "NO" : "YES") << '\n';
}

void YESflush(bool b = 1) {
    std::cout << (b ? "YES" : "NO") << std::endl;
}

void NOflush(bool b = 1) {
    std::cout << (b ? "NO" : "YES") << std::endl;
}

void Yes(bool b = 1) {
    std::cout << (b ? "Yes" : "No") << '\n';
}

void No(bool b = 1) {
    std::cout << (b ? "No" : "Yes") << '\n';
}

void Yesflush(bool b = 1) {
    std::cout << (b ? "Yes" : "No") << std::endl;
}

void Noflush(bool b = 1) {
    std::cout << (b ? "No" : "Yes") << std::endl;
}

void yes(bool b = 1) {
    std::cout << (b ? "yes" : "no") << '\n';
}

void no(bool b = 1) {
    std::cout << (b ? "no" : "yes") << '\n';
}

void yesflush(bool b = 1) {
    std::cout << (b ? "yes" : "no") << std::endl;
}

void noflush(bool b = 1) {
    std::cout << (b ? "no" : "yes") << std::endl;
}

#endif // TEMPLATE

#ifndef GRAPH_GRAPH_TEMPLATE_HPP
#define GRAPH_GRAPH_TEMPLATE_HPP 1

#include <cassert>
#include <iostream>
#include <type_traits>
#include <utility>
#include <vector>

namespace kk2 {

template <class T> struct WeightedEdge {
    int from, to, id;
    T cost;

    WeightedEdge(int to_, T cost_, int from_ = -1, int id_ = -1)
        : from(from_),
          to(to_),
          id(id_),
          cost(cost_) {}

    WeightedEdge() : from(-1), to(-1), id(-1), cost(0) {}

    operator int() const { return to; }

    WeightedEdge rev() const { return WeightedEdge(from, cost, to, id); }

    friend std::ostream &operator<<(std::ostream &os, const WeightedEdge &e) {
        if (std::is_same_v<T, bool>) return os << e.from << "->" << e.to;
        return os << e.from << "->" << e.to << ":" << e.cost;
    }
};
template <class T> using WeightedEdges = std::vector<WeightedEdge<T>>;

template <class T, bool is_directed = false>
struct WeightedGraph : std::vector<WeightedEdges<T>> {
    WeightedGraph(int n_ = 0, bool is_one_indexed = true)
        : std::vector<WeightedEdges<T>>(n_),
          n(n_),
          m(0),
          oneindexed(is_one_indexed) {}

    WeightedGraph(int n_, int m_, bool is_one_indexed = true)
        : std::vector<WeightedEdges<T>>(n_),
          n(n_),
          m(m_),
          oneindexed(is_one_indexed) {
        input();
    }

    WeightedGraph(int n_, const WeightedEdges<T> &edges_, bool is_one_indexed = true)
        : std::vector<WeightedEdges<T>>(n_),
          n(n_),
          m(0),
          oneindexed(is_one_indexed) {
        for (auto &e : edges_) { _add_edge(e.from, e.to, e.cost, m++); }
    }

    using value_type = T;
    using edge_type = WeightedEdge<T>;

    constexpr static bool directed() { return is_directed; }

    int n, m;
    bool oneindexed;
    WeightedEdges<T> edges;

    int num_vertices() const { return n; }

    int num_edges() const { return m; }

    void clear() {
        for (int i = 0; i < n; i++) (*this)[i].clear();
        edges.clear();
        m = 0;
    }

    WeightedGraph &inplace_rev() {
        static_assert(is_directed);
        WeightedEdges<T> rev(m);
        for (int i = 0; i < m; i++) { rev[i] = edges[i].rev(); }
        clear();
        for (auto &e : rev) _add_edge(e.from, e.to, e.cost, m++);
        return *this;
    }

    WeightedGraph rev() const {
        static_assert(is_directed);
        WeightedGraph res(n);
        res.m = m;
        for (int i = 0; i < m; i++) {
            res._add_edge(edges[i].to, edges[i].from, edges[i].cost, i);
        }
        return res;
    }

  private:
    void input() {
        for (int i = 0; i < m; i++) {
            int u, v;
            T w;
            std::cin >> u >> v >> w;
            if (oneindexed) {
                u--;
                v--;
            }
            _add_edge(u, v, w, i);
        }
    }

  public:
    void add_edge(int from, int to, T cost) {
        if (oneindexed) {
            from--;
            to--;
        }
        _add_edge(from, to, cost, m++);
    }

    void add_edge_naive(int from, int to, T cost) {
        _add_edge(from, to, cost, m++);
    }

  private:
    void _add_edge(int from, int to, T cost, int id) {
        (*this)[from].emplace_back(to, cost, from, id);
        if constexpr (!is_directed)
            (*this)[to].emplace_back(from, cost, to, id);
        edges.emplace_back(to, cost, from, id);
    }
};

struct UnWeightedEdge {
    int from, to, id;

    UnWeightedEdge(int to_, int from_ = -1, int id_ = -1)
        : from(from_),
          to(to_),
          id(id_) {}

    UnWeightedEdge() : from(-1), to(-1), id(-1) {}

    operator int() const { return to; }

    UnWeightedEdge rev() const { return UnWeightedEdge(from, to, id); }

    friend std::ostream &operator<<(std::ostream &os, const UnWeightedEdge &e) {
        return os << e.from << "->" << e.to;
    }
};

using UnWeightedEdges = std::vector<UnWeightedEdge>;

template <bool is_directed = false, bool is_functional = false>
struct UnWeightedGraph : std::vector<UnWeightedEdges> {
    UnWeightedGraph(int n_ = 0, bool is_one_indexed = true)
        : std::vector<UnWeightedEdges>(n_),
          n(n_),
          m(0),
          oneindexed(is_one_indexed) {}

    UnWeightedGraph(int n_, int m_, bool is_one_indexed = true)
        : std::vector<UnWeightedEdges>(n_),
          n(n_),
          m(m_),
          oneindexed(is_one_indexed) {
        input();
    }

    UnWeightedGraph(int n_, const UnWeightedEdges &edges_, bool is_one_indexed = true)
        : std::vector<UnWeightedEdges>(n_),
          n(n_),
          m(0),
          oneindexed(is_one_indexed) {
        for (auto &e : edges_) { _add_edge(e.from, e.to, m++); }
    }

    constexpr static bool directed() { return is_directed; }

    constexpr static bool functional() { return is_functional; }

    using edge_type = UnWeightedEdge;

    int n, m;
    bool oneindexed;
    UnWeightedEdges edges;

    int num_vertices() const { return n; }

    int num_edges() const { return m; }

    void clear() {
        for (int i = 0; i < n; i++) (*this)[i].clear();
        edges.clear();
        m = 0;
    }

    UnWeightedGraph &inplace_rev() {
        static_assert(is_directed);
        std::vector<std::pair<int, int>> rev(m);
        for (int i = 0; i < m; i++) { rev[i] = {edges[i].to, edges[i].from}; }
        clear();
        for (auto &&[u, v] : rev) _add_edge(u, v, m++);
        return *this;
    }

    UnWeightedGraph rev() const {
        static_assert(is_directed);
        UnWeightedGraph res(n);
        res.m = m;
        for (int i = 0; i < m; i++) {
            res._add_edge(edges[i].to, edges[i].from, i);
        }
        return res;
    }

  private:
    void input() {
        if constexpr (is_functional) {
            functional_graph();
            return;
        }
        for (int i = 0; i < m; i++) {
            int u, v;
            std::cin >> u >> v;
            if (oneindexed) {
                u--;
                v--;
            }
            _add_edge(u, v, i);
        }
    }

    void functional_graph() {
        static_assert(is_directed);
        assert(n == m);
        for (int i = 0; i < n; i++) {
            int u;
            std::cin >> u;
            if (oneindexed) u--;
            _add_edge(i, u, i);
        }
    }

  public:
    void add_edge(int from, int to) {
        if (oneindexed) {
            from--;
            to--;
        }
        _add_edge(from, to, m++);
    }

    void add_edge_naive(int from, int to) { _add_edge(from, to, m++); }

  private:
    void _add_edge(int from, int to, int id) {
        (*this)[from].emplace_back(to, from, id);
        if constexpr (!is_directed) (*this)[to].emplace_back(from, to, id);
        edges.emplace_back(to, from, id);
    }
};


template <class T, bool is_directed = false>
using WGraph = WeightedGraph<T, is_directed>;
template <bool is_directed = false, bool is_functional = false>
using Graph = UnWeightedGraph<is_directed, is_functional>;

} // namespace kk2

#endif // GRAPH_GRAPH_TEMPLATE_HPP

#ifndef GRAPH_LOWLINK_HPP
#define GRAPH_LOWLINK_HPP 1

#include <algorithm>
#include <functional>
#include <vector>

namespace kk2 {

template <class G> struct LowLink {
    int n, m;
    const G &g;
    std::vector<int> ord, low;
    std::vector<bool> root, used;

    LowLink(const G &g_)
        : n(g_.n),
          m(g_.m),
          g(g_),
          ord(n, -1),
          low(n, -1),
          root(n, false),
          used(m, false) {
        init();
    }

  private:
    void init() {
        int k = 0;
        auto dfs = [&](auto self, int u, int ei = -1) -> int {
            low[u] = ord[u] = k++;
            for (auto &e : g[u]) {
                if (e.id == ei) continue;
                if (ord[e.to] == -1) {
                    used[e.id] = true;
                    low[u] = std::min(low[u], self(self, e.to, e.id));
                }
                // back edge
                else if (ord[e.to] < ord[u]) {
                    low[u] = std::min(low[u], ord[e.to]);
                }
            }
            return low[u];
        };
        for (int u = 0; u < n; u++)
            if (ord[u] == -1) {
                dfs(dfs, u);
                root[u] = true;
            }
    }
};

} // namespace kk2

#endif // GRAPH_LOWLINK_HPP

#ifndef GRAPH_TWO_EDGE_CONNECTED_COMPONENTS_HPP
#define GRAPH_TWO_EDGE_CONNECTED_COMPONENTS_HPP 1

#include <vector>


namespace kk2 {

template <class G> struct TwoEdgeConnectedComponents : LowLink<G> {
    TwoEdgeConnectedComponents(const G &g_) : LowLink<G>(g_) { init_tecc(); }

    std::vector<int> comp;
    std::vector<std::vector<int>> group;
    G forest;

  private:
    // v is a child of u in DFS tree
    // edge(u, v) is a bridge <=> ord[u] < low[v]
    void init_tecc() {
        comp.resize(this->n, -1);
        int k = 0;
        std::vector<typename G::edge_type> bridges;
        auto dfs = [&](auto self, int now, int par, int ei) -> void {
            if (par != -1 && this->ord[par] >= this->low[now]) comp[now] = comp[par];
            else {
                comp[now] = k++;
                if (par != -1) bridges.emplace_back((this->g).edges[ei]);
            }
            for (auto &&e : this->g[now]) {
                if (comp[e.to] == -1) self(self, e.to, now, e.id);
            }
        };
        for (int i = 0; i < this->n; i++) {
            if (this->root[i]) dfs(dfs, i, -1, -1);
        }
        group.resize(k);
        for (int i = 0; i < this->n; i++) { group[comp[i]].emplace_back(i); }
        for (auto &&e : bridges) {
            e.from = comp[e.from];
            e.to = comp[e.to];
        }
        forest = G(k, bridges, this->g.oneindexed);
    }
};

} // namespace kk2

#endif // GRAPH_TWO_EDGE_CONNECTED_COMPONENTS_HPP

using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    vc<int> v(n);
    rep (i, n) cin >> v[i];

    kk2::Graph<false, false> g(n, m, true);
    kk2::TwoEdgeConnectedComponents<kk2::Graph<false, false>> tecc(g);

    int k = tecc.forest.size();
    kk2::Graph<false, false> aux = tecc.forest;
    vc<int> newv(k);
    rep (i, n) newv[tecc.comp[i]] += v[i];

    vc<int> dist(k);
    auto dfs = [&](auto self, int now, int par) -> void {
        // cout << now << " " << par << endl;
        for (auto &&e : aux[now]) {
            if (e.to == par) continue;
            dist[e.to] = dist[now] + newv[e.to];
            self(self, e.to, now);
        }
    };
    dist[0] = newv[0];
    dfs(dfs, 0, -1);
    int nextroot = max_element(all(dist)) - dist.begin();
    dist[nextroot] = newv[nextroot];
    dfs(dfs, nextroot, -1);
    cout << *max_element(all(dist)) << endl;

    return 0;
}

// converted!!
accuracy: 1
time_ms: 30
memory_kb: 41592
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

#ifdef LOCAL
#include <debug_print.hpp>
#define debug(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (static_cast<void>(0))
#endif

struct LowLink {
    int N;
    // articulation: 関節点, bridge: 橋
    vector<int> order, low, articulation;
    vector<pair<int, int>> bridge;
    LowLink(const vector<vector<int>>& G) : N(G.size()), order(N, -1), low(N, -1) {
        for (int i = 0; i < N; i++) {
            if (order[i] == -1) dfs(G, i, -1, 0);
        }
    };

    void dfs(const vector<vector<int>>& G, int pos, int parlent, int time) {
        order[pos] = low[pos] = time++;
        int child_cnt = 0;
        bool is_articulation = false, second = false;
        for (auto to : G[pos]) {
            if (order[to] == -1) {
                // to が未訪問の場合
                child_cnt++;
                dfs(G, to, pos, time);
                low[pos] = min(low[pos], low[to]);
                // order[pos] < low[to] ならば橋
                if (order[pos] < low[to]) bridge.emplace_back(minmax(pos, to));
                // 根以外で, order[pos] <= low[to] ならば関節点
                is_articulation |= parlent != -1 && order[pos] <= low[to];
            } else if (to != parlent || second) {
                // (pos, to) が後退辺 or 多重辺(後退辺)の場合
                low[pos] = min(low[pos], order[to]);
            } else {
                // to が 親の場合, もう一度 to を訪問したら (pos, to) は多重辺
                second = true;
            }
        }
        // 根かつ, 子が 2 つ以上ならば関節点
        is_articulation |= parlent == -1 && child_cnt > 1;
        if (is_articulation) articulation.emplace_back(pos);
    };
};

struct TwoEdgeConnectedComponents {
    LowLink lowlink;
    vector<int> comp;  // 頂点[i] が属する 2 重辺連結成分の番号
    vector<vector<int>> groups, tree;
    int id;
    TwoEdgeConnectedComponents(const vector<vector<int>>& G) : lowlink(G), comp(G.size(), -1), id(0) {
        for (int i = 0; i < (int)G.size(); i++) {
            if (comp[i] == -1) dfs(G, i, -1);
        }
        groups.resize(id), tree.resize(id);
        for (int i = 0; i < (int)G.size(); i++) {
            groups[comp[i]].emplace_back(i);
        }
        for (auto [u, v] : lowlink.bridge) {
            tree[comp[u]].emplace_back(comp[v]);
            tree[comp[v]].emplace_back(comp[u]);
        }
    };

    void dfs(const vector<vector<int>>& G, int pos, int parlent) {
        if (parlent != -1 && lowlink.order[parlent] >= lowlink.low[pos]) {
            // 根でないかつ, (pos, parlent) が橋でない場合
            comp[pos] = comp[parlent];
        } else {
            // 根または, (pos, parlent) が橋の場合, 新しい２重辺連結成分を作る
            comp[pos] = id++;
        }
        for (auto to : G[pos]) {
            if (comp[to] != -1) continue;
            dfs(G, to, pos);
        }
    }
};

const int INF = (1 << 30) - 1;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<int> V(N);
    for (int i = 0; i < N; i++) cin >> V[i];
    vector<vector<int>> G(N);
    for (int i = 0; i < M; i++) {
        int s, t; cin >> s >> t, s--, t--;
        G[s].emplace_back(t);
        G[t].emplace_back(s);
    }

    TwoEdgeConnectedComponents tecc(G);
    // 各 2 重辺連結成分の V の総和
    vector<int> sum(tecc.groups.size());
    for (int i = 0; i < N; i++) {
        sum[tecc.comp[i]] += V[i];
    }

    // 二重頂点連結成分を縮約した木を作り, 直径の長さを求める
    auto G2 = tecc.tree;
    vector<int> dist(G2.size(), -1);
    queue<int> que;
    dist[0] = sum[0];
    que.emplace(0);
    while (!que.empty()) {
        int pos = que.front(); que.pop();
        for (auto to: G2[pos]) {
            if (dist[to] != -1) continue;
            dist[to] = dist[pos] + sum[to];
            que.emplace(to);
        }
    }
    int max_pos = max_element(dist.begin(), dist.end()) - dist.begin();
    dist.assign(G2.size(), -1);
    dist[max_pos] = sum[max_pos];
    que.emplace(max_pos);
    while (!que.empty()) {
        int pos = que.front(); que.pop();
        for (auto to: G2[pos]) {
            if (dist[to] != -1) continue;
            dist[to] = dist[pos] + sum[to];
            que.emplace(to);
        }
    }
    cout << *max_element(dist.begin(), dist.end()) << '\n';
}
accuracy: 1
time_ms: 30
memory_kb: 40936
final_rank: 15

code_snippet: #include <bits/stdc++.h>




namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa


namespace zawa {

void SetFastIO() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
}

void SetPrecision(u32 dig) {
    std::cout << std::fixed << std::setprecision(dig);
}

} // namespace zawa



namespace zawa {

class LowlinkResponse {
public:
    LowlinkResponse() = default;

    LowlinkResponse(const std::vector<u32>& articulation, const std::vector<bool>& bridge)
        : articulation_{articulation}, bridge_{bridge} {}

    inline bool isArticulation(u32 v) const {
        assert(v < articulation_.size());
        return articulation_[v] > 1u;
    }

    inline u32 cut(u32 v) const {
        assert(v < articulation_.size());
        return articulation_[v];
    }

    inline bool isBridge(u32 i) const {
        assert(i < bridge_.size());
        return bridge_[i];
    }

private:
    std::vector<u32> articulation_;
    std::vector<bool> bridge_;
};

class Lowlink {
private:
    static constexpr u32 INVALID{static_cast<u32>(-1)};
    usize n_{}, m_{};
    std::vector<std::vector<std::pair<u32, u32>>> g_;
    std::vector<std::pair<u32, u32>> e_;

    void dfs(u32 v, u32 p, u32& t, std::vector<u32>& articulation, 
            std::vector<bool>& bridge, std::vector<u32>& in, std::vector<u32>& low) const {
        low[v] = in[v] = t++;
        u32 deg{}; 
        for (const auto& [x, i] : g_[v]) {
            if (in[x] == INVALID) {
                deg++;
                dfs(x, v, t, articulation, bridge, in, low);
                low[v] = std::min(low[v], low[x]);
                if (p != INVALID and low[x] >= in[v]) {
                    articulation[v]++;
                }
                if (low[x] > in[v]) {
                    bridge[i] = true;
                }
            }
            else if (x != p) {
                low[v] = std::min(low[v], in[x]);
            }
        }
        if (p == INVALID) {
            articulation[v] = deg;
        }
    }

public:
    constexpr usize size() const noexcept {
        return n_;
    }

    constexpr usize edgeSize() const noexcept {
        return m_;
    }

    Lowlink() = default;

    Lowlink(usize n) 
        : n_{n}, m_{}, g_(n) {
        g_.shrink_to_fit();
    }
    
    usize addEdge(u32 u, u32 v) {
        usize res{m_++};
        e_.emplace_back(u, v);
        g_[u].emplace_back(v, res);
        g_[v].emplace_back(u, res);
        return res;
    }

    const std::vector<std::pair<u32, u32>>& operator[](u32 v) const noexcept {
        assert(v < size());
        return g_[v];
    }
    const std::pair<u32, u32>& edge(u32 i) const noexcept {
        assert(i < edgeSize());
        return e_[i];
    }

    LowlinkResponse build() const {
        u32 t{};
        std::vector<u32> articulation(size(), 1u), in(size(), INVALID), low(size());
        std::vector<bool> bridge(edgeSize());
        for (u32 v{} ; v < size() ; v++) if (in[v] == INVALID) {
            dfs(v, INVALID, t, articulation, bridge, in, low);
        }
        return LowlinkResponse{ articulation, bridge };
    }

};

} // namespace zawa
using namespace zawa;

int main() {
    SetFastIO();

    int N, M;
    std::cin >> N >> M;
    Lowlink low(N);
    std::vector<std::vector<std::pair<int, int>>> g(N);
    std::vector<int> V(N);
    std::vector<std::pair<int, int>> E(M);
    for (auto& v : V) std::cin >> v;
    for (int i{} ; i < M ; i++) {
        int s, t;
        std::cin >> s >> t;
        s--; t--;
        low.addEdge(s, t);
        g[s].push_back(std::pair(t, i));
        g[t].push_back(std::pair(s, i));
        E[i] = std::pair{ s, t };
    }
    auto brg{low.build()};
    std::vector<int> val;
    std::vector<std::vector<int>> g2;
    std::vector<int> col(N, -1);
    auto dfs{[&](auto dfs, int v, int& sum, int c) -> void {
        col[v] = c;
        sum += V[v];
        for (auto [x, i] : g[v]) if (!brg.isBridge(i) and col[x] == -1) {
            dfs(dfs, x, sum, c);
        }
    }};
    for (int i{} ; i < N ; i++) if (col[i] == -1) {
        int sum{};
        dfs(dfs, i, sum, (int)g2.size());
        g2.push_back(std::vector<int>{});
        val.push_back(sum);
    }
    for (auto [s, t] : E) {
        if (col[s] != col[t]) {
            g2[col[s]].push_back(col[t]);
            g2[col[t]].push_back(col[s]);
        }
    }
    for (int i{} ; i < (int)g2.size() ; i++) {
        std::sort(g2[i].begin(), g2[i].end());
        g2[i].erase(std::unique(g2[i].begin(), g2[i].end()), g2[i].end());
    }
    std::vector<int> d1(g2.size(), -1);
    d1[0] = val[0];
    std::queue<int> que;
    que.push(0);
    while (que.size()) {
        int v{que.front()};
        que.pop();
        for (auto x : g2[v]) if (d1[x] == -1) {
            d1[x] = d1[v] + val[x];
            que.push(x);
        }
    }
    int p{(int)std::distance(d1.begin(), std::max_element(d1.begin(), d1.end()))};
    std::vector<int> d2(g2.size(), -1);
    d2[p] = val[p];
    que.push(p);
    while (que.size()) {
        int v{que.front()};
        que.pop();
        for (auto x : g2[v]) if (d2[x] == -1) {
            d2[x] = d2[v] + val[x];
            que.push(x);
        }
    }
    std::cout << *std::max_element(d2.begin(), d2.end()) << '\n';
}
accuracy: 1
time_ms: 30
memory_kb: 35708
final_rank: 8

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

struct unionfind {
	long long n;
	vector<long long> p,s;
	unionfind(long long n) : n(n) {
		p.resize(n,-1ll);
		s.resize(n,1ll);
	}
	long long root(long long x){
		while(p[x] != -1ll){
			x = p[x];
		}
		return x;
	}
	void merge(long long u,long long v){
		long long ru = root(u),rv = root(v);
		if(ru == rv) return;
		if(s[ru] < s[rv]){
			p[ru] = rv;
			s[rv] += s[ru];
		}else{
			p[rv] = ru;
			s[ru] += s[rv];
		}
	}
	bool same(long long u,long long v){
		return root(u) == root(v);
	}
};
int main()
{
	long long n,m;
	cin >> n >> m;
	vector<vector<long long>> g(n,vector<long long>());
	vector<long long> a(n);
	for(long long i = 0ll;i < n;i++){
		cin >> a[i];
	}
	for(long long i = 0ll;i < m;i++){
		long long u,v;
		cin >> u >> v;
		u--;v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	vector<vector<long long>> tr;
	vector<long long> cou;
	{
		vector<pair<long long,long long>> t(n,{-1ll,LLONG_MAX});
		long long now = 0ll;
		auto dfs = [&](auto dfs,long long x,long long l) -> void {
			t[x].first = now;
			now++;
			if(!g[x].empty()){
				for(long long i : g[x]){
					if(i == l) continue;
					if(t[i].first != -1ll){
						t[x].second = min(t[x].second,t[i].first);
					}else{
						dfs(dfs,i,x);
						t[x].second = min(t[x].second,t[i].second);
					}
				}
			}
		};
		dfs(dfs,0ll,-1ll);
		vector<vector<long long>> nex(n,vector<long long>());
		unionfind uf(n);
		for(long long i = 0ll;i < n;i++){
			if(g[i].empty()) continue;
			for(long long j : g[i]){
				if(t[i].first > t[j].first) continue;
				if(t[i].first >= t[j].second){
					nex[i].push_back(j);
					nex[j].push_back(i);
					uf.merge(i,j);
				}
			}
		}
		set<long long> s;
		for(long long i = 0ll;i < n;i++){
			s.insert(uf.root(i));
		}
		map<long long,long long> x;
		now = 0ll;
		for(auto itr = s.begin();itr != s.end();itr++){
			x[*itr] = now;
			now++;
		}
		tr.resize(s.size(),{});
		cou.resize(s.size(),0ll);
		for(long long i = 0ll;i < n;i++){
			if(g[i].empty()) continue;
			for(long long j : g[i]){
				if(t[i].first > t[j].first) continue;
				if(t[i].first < t[j].second){
					tr[x[uf.root(i)]].push_back(x[uf.root(j)]);
					tr[x[uf.root(j)]].push_back(x[uf.root(i)]);
				}
			}
			cou[x[uf.root(i)]] += a[i];
		}
	}
	long long ans = 0ll;
	pair<long long,long long> ma(-1ll,-1ll);
	{
		vector<long long> dist(n,-1ll);
		queue<long long> q;
		dist[0ll] = cou[0ll];
		q.push(0ll);
		while(!q.empty()){
			long long it = q.front();
			q.pop();
			if(dist[it] > ma.first){
				ma.first = dist[it];
				ma.second = it;
			}
			for(long long i : tr[it]){
				if(dist[i] != -1ll) continue;
				dist[i] = dist[it] + cou[i];
				q.push(i);
			}
		}
	}
	{
		vector<long long> dist(n,-1ll);
		queue<long long> q;
		dist[ma.second] = cou[ma.second];
		q.push(ma.second);
		ma = {-1ll,-1ll};
		while(!q.empty()){
			long long it = q.front();
			q.pop();
			if(dist[it] > ma.first){
				ma.first = dist[it];
				ma.second = it;
			}
			for(long long i : tr[it]){
				if(dist[i] != -1ll) continue;
				dist[i] = dist[it] + cou[i];
				q.push(i);
			}
		}
	}
	cout << ma.first << endl;
}
accuracy: 1
time_ms: 130
memory_kb: 42868
final_rank: 19

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


#include <algorithm>
#include <cassert>
#include <vector>

namespace atcoder {

struct dsu {
  public:
    dsu() : _n(0) {}
    explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}

    int merge(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
        parent_or_size[x] += parent_or_size[y];
        parent_or_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return leader(a) == leader(b);
    }

    int leader(int a) {
        assert(0 <= a && a < _n);
        if (parent_or_size[a] < 0) return a;
        return parent_or_size[a] = leader(parent_or_size[a]);
    }

    int size(int a) {
        assert(0 <= a && a < _n);
        return -parent_or_size[leader(a)];
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }

  private:
    int _n;
    std::vector<int> parent_or_size;
};

}  // namespace atcoder

using namespace atcoder;

int main() {
  int N, M;
  cin >> N >> M;
  vector<int> v(N);
  vector<vector<int>> G(N);
  for(int i = 0; i < N; i++) {
    cin >> v[i];
  }
  for(int i = 0; i < M; i++) {
    int s, t;
    cin >> s >> t;
    s--, t--;
    G[s].push_back(t);
    G[t].push_back(s);
  }
  dsu uf(N);
  { // lowlink begin
    int tim = 0;
    vector<int> ord(N), low(N);
    vector<bool> vis(N);
    auto dfs = [&](auto dfs, int cur, int par) -> void {
      vis[cur] = true;
      ord[cur] = tim++;
      low[cur] = ord[cur];
      for(const int &nxt : G[cur]) {
        if(!vis[nxt]) {
          dfs(dfs, nxt, cur);
          low[cur] = min(low[cur], low[nxt]);
          if(ord[cur] >= low[nxt]) uf.merge(cur, nxt);
        }else if(nxt != par) {
          low[cur] = min(low[cur], ord[nxt]);
        }
      }
    };
    dfs(dfs, 0, -1);
  } // lowlink end
  { // contraction begin
    for(vector<int> group : uf.groups()) {
      int ld = uf.leader(group.front());
      for(int mem : group) {
        if(mem == ld) continue;
        v[ld] += v[mem];
        G[ld].insert(G[ld].end(), G[mem].begin(), G[mem].end());
        v[mem] = 0;
        G[mem].clear();
      }
      for(int &nxt : G[ld]) {
        nxt = uf.leader(nxt);
      }
      sort(G[ld].begin(), G[ld].end());
      G[ld].erase(unique(G[ld].begin(), G[ld].end()), G[ld].end());
    }
  } // contraction end
  dsu uf_gc(N);
  for(int i = 0; i < N; i++) {
    for(const int &nxt : G[i]) {
      uf_gc.merge(i, nxt);
    }
  }
  int ans = 0;
  { // calc diameter begin
    vector<int> dp(N);
    vector<bool> vis(N);
    auto dfs = [&](auto dfs, int cur) -> void {
      vis[cur] = true;
      for(const int &nxt : G[cur]) {
        if(!vis[nxt]) {
          dp[nxt] = dp[cur]+v[nxt];
          dfs(dfs, nxt);
        }
      }
    };
    for(vector<int> group : uf_gc.groups()) {
      int ld = uf_gc.leader(group.front());
      dp[ld] = v[ld];
      dfs(dfs, ld);
      for(int mem : group) {
        if(dp[mem] > dp[ld]) ld = mem;
      }
      for(int mem : group) {
        dp[mem] = 0;
        vis[mem] = false;
      }
      dp[ld] = v[ld];
      dfs(dfs, ld);
      for(int mem : group) {
        ans = max(ans, dp[mem]);
      }
    }
  } // calc diameter end
  cout << ans << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 37220
final_rank: 17

code_snippet: #include <bits/stdc++.h>

struct UnionFind {
    std::vector<int> data;
    UnionFind(int n): data(n, -1) {}
    int leader(int x) {
        if (data[x] < 0) return x;
        return data[x] = leader(data[x]);
    }
    bool merge(int lhs, int rhs) {
        lhs = leader(lhs);
        rhs = leader(rhs);
        if (lhs == rhs) return false;
        if (data[lhs] < data[rhs]) std::swap(lhs, rhs);
        data[rhs] += data[lhs];
        data[lhs] = rhs;
        return true;
    }
    bool same(int lhs, int rhs) {
        return leader(lhs) == leader(rhs);
    }
    std::vector<std::vector<int>> groups() {
        std::vector<std::vector<int>> res(data.size());
        for (int i = 0; i < (int)data.size(); i++) {
            res[leader(i)].push_back(i);
        }
        auto it = std::remove_if(res.begin(), res.end(), [](const std::vector<int>& vec) { return vec.empty(); });
        res.erase(it, res.end());
        return res;
    }
};

int main() {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> vs(n);
    for (int i = 0; i < n; i++) std::cin >> vs[i];
    std::vector<std::vector<int>> graph(n);
    for (int i = 0; i < m; i++) {
        int u, v;
        std::cin >> u >> v;
        u--; v--;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    UnionFind uf(n);
    {
        std::vector<int> in(n, -1);
        std::vector<int> low(n, -1);
        int now = 0;
        auto dfs = [&](auto self, int u, int p) -> void {
            low[u] = in[u] = now++;
            for (auto v: graph[u]) {
                if (v == p) continue;
                if (low[v] == -1) {
                    self(self, v, u);
                    low[u] = std::min(low[u], low[v]);
                } else {
                    low[u] = std::min(low[u], in[v]);
                }
            }
            if (p != -1 && low[u] <= in[p]) {
                uf.merge(u, p);
            }
        };
        dfs(dfs, 0, -1);
    }
    std::vector<int> nodes(n);
    std::vector<std::vector<int>> tree(n);
    for (int i = 0; i < n; i++) {
        nodes[uf.leader(i)] += vs[i];
    }
    for (int u = 0; u < n; u++) {
        for (auto v: graph[u]) {
            if (uf.same(u, v)) continue;
            tree[uf.leader(u)].push_back(uf.leader(v));
        }
    }
    const int root = uf.leader(0);
    int ans = 0;
    auto calc = [&](auto self, int u, int p) -> int {
        std::vector<int> res;
        for (auto v: tree[u]) {
            if (v == p) continue;
            res.push_back(self(self, v, u));
        }
        std::sort(res.begin(), res.end(), std::greater<int>());
        if (res.size() >= 2) {
            ans = std::max(ans, nodes[u] + res[0] + res[1]);
            return nodes[u] + res[0];
        } else if (res.size() >= 1) {
            ans = std::max(ans, nodes[u] + res[0]);
            return nodes[u] + res[0];
        } else {
            ans = std::max(ans, nodes[u]);
            return nodes[u];
        }
    };
    calc(calc, root, -1);
    std::cout << ans << '\n';
}
accuracy: 1
time_ms: 60
memory_kb: 30748
final_rank: 9

code_snippet: #include <bits/stdc++.h>

struct UnionFind {
    std::vector<int> data;
    UnionFind(int n): data(n, -1) {}
    int leader(int x) {
        if (data[x] < 0) return x;
        return data[x] = leader(data[x]);
    }
    bool merge(int lhs, int rhs) {
        lhs = leader(lhs);
        rhs = leader(rhs);
        if (lhs == rhs) return false;
        if (data[lhs] < data[rhs]) std::swap(lhs, rhs);
        data[rhs] += data[lhs];
        data[lhs] = rhs;
        return true;
    }
    bool same(int lhs, int rhs) {
        return leader(lhs) == leader(rhs);
    }
    std::vector<std::vector<int>> groups() {
        std::vector<std::vector<int>> res(data.size());
        for (int i = 0; i < (int)data.size(); i++) {
            res[leader(i)].push_back(i);
        }
        auto it = std::remove_if(res.begin(), res.end(), [](const std::vector<int>& vec) { return vec.empty(); });
        res.erase(it, res.end());
        return res;
    }
};

int main() {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> vs(n);
    for (int i = 0; i < n; i++) std::cin >> vs[i];
    std::vector<std::vector<int>> graph(n);
    for (int i = 0; i < m; i++) {
        int u, v;
        std::cin >> u >> v;
        u--; v--;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    UnionFind uf(n);
    {
        std::vector<int> in(n, -1);
        std::vector<int> low(n, -1);
        int now = 0;
        auto dfs = [&](auto self, int u, int p) -> void {
            low[u] = in[u] = now++;
            for (auto v: graph[u]) {
                if (v == p) continue;
                if (low[v] == -1) {
                    self(self, v, u);
                    low[u] = std::min(low[u], low[v]);
                } else {
                    low[u] = std::min(low[u], in[v]);
                }
            }
            if (p != -1 && low[u] <= in[p]) {
                uf.merge(u, p);
            }
        };
        dfs(dfs, 0, -1);
    }
    std::vector<int> nodes(n);
    std::vector<std::vector<int>> tree(n);
    for (int i = 0; i < n; i++) {
        nodes[uf.leader(i)] += vs[i];
    }
    for (int u = 0; u < n; u++) {
        for (auto v: graph[u]) {
            if (uf.same(u, v)) continue;
            tree[uf.leader(u)].push_back(uf.leader(v));
        }
    }
    for (int i = 0; i < n; i++) {
        std::sort(tree[i].begin(), tree[i].end());
        tree[i].erase(std::unique(tree[i].begin(), tree[i].end()), tree[i].end());
    }
    const int root = uf.leader(0);
    int ans = 0;
    auto calc = [&](auto self, int u, int p) -> int {
        std::vector<int> res;
        for (auto v: tree[u]) {
            if (v == p) continue;
            res.push_back(self(self, v, u));
        }
        std::sort(res.begin(), res.end(), std::greater<int>());
        if (res.size() >= 2) {
            ans = std::max(ans, nodes[u] + res[0] + res[1]);
            return nodes[u] + res[0];
        } else if (res.size() >= 1) {
            ans = std::max(ans, nodes[u] + res[0]);
            return nodes[u] + res[0];
        } else {
            ans = std::max(ans, nodes[u]);
            return nodes[u];
        }
    };
    calc(calc, root, -1);
    std::cout << ans << '\n';
}
accuracy: 1
time_ms: 60
memory_kb: 30848
final_rank: 10

code_snippet: #include <bits/stdc++.h>

struct Edge {
    Edge(int f, int t, int i): from(f), to(t), id(i) {}
    int from;
    int to;
    int id;
};

std::vector<int> bridge(const std::vector<std::vector<Edge>>& graph) {
    int n = graph.size();
    std::vector<int> in(n, -1);
    std::vector<int> low(n, -1);
    int now = 0;
    std::vector<int> res;
    auto dfs = [&](auto self, int u, int p) -> void {
        in[u] = now++;
        low[u] = in[u];
        for (auto e: graph[u]) {
            if (e.to == p) continue;
            if (low[e.to] == -1) {
                self(self, e.to, u);
                low[u] = std::min(low[u], low[e.to]);
                if (in[u] < low[e.to]) {
                    res.push_back(e.id);
                }
            } else {
                low[u] = std::min(low[u], in[e.to]);
            }
        }
    };
    dfs(dfs, 0, -1);
    return res;
}

bool is_tree(const std::vector<std::vector<Edge>>& graph) {
    int n = graph.size();
    std::vector<bool> already(n);
    auto dfs = [&](auto self, int u, int p) -> bool {
        already[u] = true;
        for (auto e: graph[u]) {
            if (e.to == p) continue;
            if (already[e.to]) {
                return false;
            } else {
                if (!self(self, e.to, u)) return false;
            }
        }
        return true;
    };
    return dfs(dfs, 0, -1);
}

int main() {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> value(n);
    for (int i = 0; i < n; i++) std::cin >> value[i];
    std::vector<std::vector<Edge>> graph(n);
    std::vector<Edge> edges;
    for (int i = 0; i < m; i++) {
        int u, v;
        std::cin >> u >> v;
        u--; v--;
        graph[u].emplace_back(u, v, i);
        graph[v].emplace_back(v, u, i);
        edges.emplace_back(u, v, i);
    }
    std::vector<bool> is_bridge(m, false);
    for (int id: bridge(graph)) {
        is_bridge[id] = true;
    }

    int group_num = 0;
    std::vector<int> group_id(n, -1);
    auto dfs = [&](auto self, int u, int color) -> void {
        assert(group_id[u] == -1);
        group_id[u] = color;
        for (auto e: graph[u]) {
            if (is_bridge[e.id]) continue;
            if (group_id[e.to] == -1) {
                self(self, e.to, color);
            } else {
                assert(group_id[e.to] == color);
            }
        }
    };
    for (int i = 0; i < n; i++) {
        if (group_id[i] == -1) {
            dfs(dfs, i, group_num++);
        }
    }
    std::vector<int> group_value(group_num);
    for (int i = 0; i < n; i++) {
        group_value[group_id[i]] += value[i];
    }
    std::vector<std::vector<Edge>> tree(group_num);
    for (auto [u, v, i]: edges) {
        if (is_bridge[i]) {
            assert(group_id[u] != group_id[v]);
            tree[group_id[u]].emplace_back(group_id[u], group_id[v], -1);
            tree[group_id[v]].emplace_back(group_id[v], group_id[u], -1);
        }
    }
    assert(is_tree(tree));
    int ans = 0;
    auto calc = [&](auto self, int u, int p) -> int {
        std::vector<int> res;
        for (auto e: tree[u]) {
            if (e.to == p) continue;
            res.push_back(self(self, e.to, u));
        }
        int cur = group_value[u];
        std::sort(res.begin(), res.end(), std::greater<int>());
        for (int i = 0; i < std::min((int)res.size(), 2); i++) {
            cur += res[i];
        }
        ans = std::max(ans, cur);
        if (res.size() == 0) return group_value[u];
        return group_value[u] + res.front();
    };
    calc(calc, 0, -1);
    std::cout << ans << '\n';
}
accuracy: 1
time_ms: 60
memory_kb: 31968
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<b;i++)
using ll = long long;
template<class T> bool chmin(T &a,const T b){if(a>b){a=b;return 1;}return 0;}
template<class T> bool chmax(T &a,const T b){if(a<b){a=b;return 1;}return 0;}
const int INF = (1<<30)-1;
#define all(p) p.begin(),p.end()

int main(){
	int N,M;
    cin>>N>>M;
    vector<int> V(N);
    rep(i,0,N) cin>>V[i];
    vector<vector<int>> G(N);
    rep(i,0,M){
        int a,b;
        cin>>a>>b;
        a--,b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    vector<int> pare(N,-1);
    pare[0]=-2;
    vector<int> dp(N),deep(N);
    auto dfs=[&](auto self,int ind)->void{
        for(auto x:G[ind]){
            if(pare[x]==-1){
                pare[x]=ind;
                deep[x]=deep[ind]+1;
                self(self,x);
            }
            else if(pare[ind]!=x&&deep[x]<deep[ind]){
                dp[ind]++;
                dp[x]--;
            }
        }
        if(pare[ind]!=-2) dp[pare[ind]]+=dp[ind];
    };
    dfs(dfs,0);
    //rep(i,0,N) cout<<i<<" "<<dp[i]<<endl;
    vector<vector<int>> H;
    vector<int> n_V;
    vector<int> seen(N,-1);
    int L=0;
    rep(i,0,N){
        if(seen[i]!=-1) continue;
        seen[i]=L;
        n_V.push_back(0);
        vector<int> order={i};
        rep(j,0,(int)(order.size())){
            int a=order[j];
            n_V[L]+=V[a];
            for(auto x:G[a]){
                if(seen[x]!=-1) continue;
                if(pare[a]==x&&dp[a]==0) continue;
                if(pare[x]==a&&dp[x]==0) continue;
                seen[x]=seen[a];
                order.push_back(x);
            }
        }
        L++;
    }
    H.resize(L,{});
    rep(i,0,N){
        for(auto x:G[i]){
            if(seen[x]!=seen[i]) H[seen[x]].push_back(seen[i]);
        }
    }
    pare[0]=-2;
    vector<int> order={0};
    rep(i,1,L) pare[i]=-1;
    rep(i,0,L){
        int a=order[i];
        for(auto x:H[a]){
            if(pare[x]==-1){
                pare[x]=a;
                order.push_back(x);
            }
        }
    }
    vector<int> A(L),B(L);
    int ans=0;
    reverse(all(order));
    rep(i,0,L){
        int a=order[i];
        for(auto x:H[a]){
            if(pare[a]==x) continue;
            if(chmax(B[a],A[x])){
                if(A[a]<B[a]) swap(A[a],B[a]);
            }
        }
        //cout<<a<<" "<<A[a]<<" "<<B[a]<<" "<<n_V[a]<<endl;
        A[a]+=n_V[a];
        chmax(ans,A[a]+B[a]);
    }
    cout<<ans<<"\n";
}
accuracy: 1
time_ms: 50
memory_kb: 26888
final_rank: 4

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 0415.cc: Dungeion 3
 */

#include<cstdio>
#include<vector>
#include<stack>
#include<algorithm>
 
using namespace std;

/* constant */

const int MAX_N = 100000;

/* typedef */

typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<vi> vvi;
typedef pair<int,int> pii;
typedef vector<pii> vpii;
typedef stack<int> si;

/* global variables */

int vs[MAX_N], gvs[MAX_N], gids[MAX_N];
vi nbrs[MAX_N], gnbrs[MAX_N];
int ps[MAX_N], cis[MAX_N], xs0[MAX_N], xs1[MAX_N];

/* subroutines */

void bcc_visit(const vi *nbrs, int v, int u, vpii& brdg, vvi& tecomp,
	       si& roots, si& S, vb& inS, vi& num, int& time) {
  num[v] = ++time;
  S.push(v); inS[v] = true;
  roots.push(v);

  const vi& nbrv = nbrs[v];
  for (vi::const_iterator vit = nbrv.begin(); vit != nbrv.end(); vit++) {
    const int& w = *vit;
    if (num[w] == 0)
      bcc_visit(nbrs, w, v, brdg, tecomp, roots, S, inS, num, time);
    else if (u != w && inS[w])
      while (num[roots.top()] > num[w]) roots.pop();
  }

  if (v == roots.top()) {
    brdg.push_back(pii(u, v));
    tecomp.push_back(vi());
    for (;;) {
      int w = S.top(); S.pop(); inS[w] = false;
      tecomp.back().push_back(w);
      if (v == w) break;
    }
    roots.pop();
  }
}

void calc_bcc(const int n, const vi *nbrs, vpii& brdg, vvi& tecomp) {
  vi num(n);
  vb inS(n);
  si roots, S;
  int time = 0;

  for (int u = 0; u < n; u++)
    if (num[u] == 0) {
      bcc_visit(nbrs, u, n, brdg, tecomp, roots, S, inS, num, time);
      brdg.pop_back();
    }
}

/* main */

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; i++) scanf("%d", vs + i);

  for (int i = 0; i < m; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    u--, v--;
    nbrs[u].push_back(v);
    nbrs[v].push_back(u);
  }

  vpii brdg;
  vvi tcmp;
  calc_bcc(n, nbrs, brdg, tcmp);
  int gn = tcmp.size();

  for (int i = 0; i < gn; i++) {
    //printf("%d:", i);
    for (auto u: tcmp[i]) {
      gvs[i] += vs[u], gids[u] = i;
      //printf(" %d", u);
    }
    //printf(" : gv=%d\n", gvs[i]);
  }

  for (auto e: brdg) {
    int u = gids[e.first], v = gids[e.second];
    if (u != v) {
      //printf("%d,%d\n", u, v);
      gnbrs[u].push_back(v);
      gnbrs[v].push_back(u);
    }
  }

  int maxd = 0;
  ps[0] = -1;
  for (int u = 0; u >= 0;) {
    vi &gnbru = gnbrs[u];
    int up = ps[u];

    if (cis[u] < gnbru.size()) {
      int v = gnbru[cis[u]++];
      if (v != up) {
	ps[v] = u;
	u = v;
      }
    }
    else {
      xs0[u] += gvs[u];
      maxd = max(maxd, xs0[u] + xs1[u]);

      if (up >= 0) {
	if (xs0[up] < xs0[u]) xs1[up] = xs0[up], xs0[up] = xs0[u];
	else if (xs1[up] < xs0[u]) xs1[up] = xs0[u];
      }

      u = up;
    }
  }

  printf("%d\n", maxd);
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 38264
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n)  for(long long i=0;i<(long long)(n);i++)
#define REP(i,k,n) for(long long i=k;i<(long long)(n);i++)
#define pb emplace_back
#define lb(v,k) (lower_bound(all(v),(k))-v.begin())
#define ub(v,k) (upper_bound(all(v),(k))-v.begin())
#define fi first
#define se second
#define pi M_PI
#define PQ(T) priority_queue<T>
#define SPQ(T) priority_queue<T,vector<T>,greater<T>>
#define dame(a) {out(a);return 0;}
#define decimal cout<<fixed<<setprecision(15);
#define all(a) a.begin(),a.end()
#define rsort(a) {sort(all(a));reverse(all(a));}
#define dupli(a) {sort(all(a));a.erase(unique(all(a)),a.end());}
#define popcnt __builtin_popcountll
typedef long long ll;
typedef pair<ll,ll> P;
typedef tuple<ll,ll,ll> PP;
typedef tuple<ll,ll,ll,ll> PPP;
using vi=vector<ll>;
using vvi=vector<vi>;
using vvvi=vector<vvi>;
using vvvvi=vector<vvvi>;
using vp=vector<P>;
using vvp=vector<vp>;
using vb=vector<bool>;
using vvb=vector<vb>;
const ll inf=1001001001001001001;
const ll INF=1001001001;
const ll mod=998244353;
const double eps=1e-10;
template<class T> bool chmin(T&a,T b){if(a>b){a=b;return true;}return false;}
template<class T> bool chmax(T&a,T b){if(a<b){a=b;return true;}return false;}
template<class T> void out(T a){cout<<a<<'\n';}
template<class T> void outp(T a){cout<<'('<<a.fi<<','<<a.se<<')'<<'\n';}
template<class T> void outvp(T v){rep(i,v.size())cout<<'('<<v[i].fi<<','<<v[i].se<<')';cout<<'\n';}
template<class T> void outvvp(T v){rep(i,v.size())outvp(v[i]);}
template<class T> void outv(T v){rep(i,v.size()){if(i)cout<<' ';cout<<v[i];}cout<<'\n';}
template<class T> void outvv(T v){rep(i,v.size())outv(v[i]);}
template<class T> bool isin(T x,T l,T r){return (l)<=(x)&&(x)<=(r);}
template<class T> void yesno(T b){if(b)out("yes");else out("no");}
template<class T> void YesNo(T b){if(b)out("Yes");else out("No");}
template<class T> void YESNO(T b){if(b)out("YES");else out("NO");}
template<class T> void outset(T s){auto itr=s.begin();while(itr!=s.end()){if(itr!=s.begin())cout<<' ';cout<<*itr;itr++;}cout<<'\n';}
void outs(ll a,ll b){if(a>=inf-100)out(b);else out(a);}
ll gcd(ll a,ll b){if(b==0)return a;return gcd(b,a%b);}
ll modpow(ll a,ll b){ll res=1;a%=mod;while(b){if(b&1)res=res*a%mod;a=a*a%mod;b>>=1;}return res;}

int main(){
    ll n,m;cin>>n>>m;
    vi v(n);rep(i,n)cin>>v[i];
    vvp g(n);
    rep(i,m){
        ll a,b;cin>>a>>b;a--;b--;
        g[a].pb(b,i);g[b].pb(a,i);
    }
    vi lk(n),dep(n,-1);
    vb is_bridge(m,false);
    function<void(ll,ll,ll)> dfs=[&](ll i,ll p,ll e){
        lk[i]=dep[i];
        for(P x:g[i])if(x.fi!=p){
            if(dep[x.fi]==-1){
                dep[x.fi]=dep[i]+1;
                dfs(x.fi,i,x.se);
                chmin(lk[i],lk[x.fi]);
            }
            else chmin(lk[i],dep[x.fi]);
        }
        if(lk[i]==dep[i]&&i)is_bridge[e]=true;
    };
    dep[0]=0;dfs(0,-1,-1);
    vi gr(n,-1);
    ll num_gr=0;
    rep(i,n)if(gr[i]==-1){
        gr[i]=num_gr;
        queue<ll> que;que.push(i);
        while(!que.empty()){
            ll t=que.front();que.pop();
            for(auto x:g[t])if(!is_bridge[x.se]){
                if(gr[x.fi]==-1){
                    gr[x.fi]=num_gr;que.push(x.fi);
                }
            }
        }
        num_gr++;
    }
    vvi G(num_gr);
    rep(i,n)for(auto x:g[i])if(is_bridge[x.se])G[gr[i]].pb(gr[x.fi]);
    vi val(num_gr);
    rep(i,n)val[gr[i]]+=v[i];
    vi dp(num_gr);
    ll ans=0;
    function<void(ll,ll)> dfs2=[&](ll i,ll p){
        vi al;
        for(ll x:G[i])if(x!=p){
            dfs2(x,i);
            al.pb(dp[x]);
        }
        rsort(al);
        chmax(ans,val[i]);
        if(al.size())chmax(ans,al[0]+val[i]);
        if(al.size()>1)chmax(ans,al[0]+al[1]+val[i]);
        dp[i]=val[i];if(al.size())dp[i]+=al[0];
    };dfs2(0,-1);
    out(ans);
}
accuracy: 1
time_ms: 60
memory_kb: 31244
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n)  for(long long i=0;i<(long long)(n);i++)
#define REP(i,k,n) for(long long i=k;i<(long long)(n);i++)
#define pb emplace_back
#define lb(v,k) (lower_bound(all(v),(k))-v.begin())
#define ub(v,k) (upper_bound(all(v),(k))-v.begin())
#define fi first
#define se second
#define pi M_PI
#define PQ(T) priority_queue<T>
#define SPQ(T) priority_queue<T,vector<T>,greater<T>>
#define dame(a) {out(a);return 0;}
#define decimal cout<<fixed<<setprecision(15);
#define all(a) a.begin(),a.end()
#define rsort(a) {sort(all(a));reverse(all(a));}
#define dupli(a) {sort(all(a));a.erase(unique(all(a)),a.end());}
#define popcnt __builtin_popcountll
typedef long long ll;
typedef pair<ll,ll> P;
typedef tuple<ll,ll,ll> PP;
typedef tuple<ll,ll,ll,ll> PPP;
using vi=vector<ll>;
using vvi=vector<vi>;
using vvvi=vector<vvi>;
using vvvvi=vector<vvvi>;
using vp=vector<P>;
using vvp=vector<vp>;
using vb=vector<bool>;
using vvb=vector<vb>;
const ll inf=1001001001001001001;
const ll INF=1001001001;
const ll mod=998244353;
const double eps=1e-10;
template<class T> bool chmin(T&a,T b){if(a>b){a=b;return true;}return false;}
template<class T> bool chmax(T&a,T b){if(a<b){a=b;return true;}return false;}
template<class T> void out(T a){cout<<a<<'\n';}
template<class T> void outp(T a){cout<<'('<<a.fi<<','<<a.se<<')'<<'\n';}
template<class T> void outvp(T v){rep(i,v.size())cout<<'('<<v[i].fi<<','<<v[i].se<<')';cout<<'\n';}
template<class T> void outvvp(T v){rep(i,v.size())outvp(v[i]);}
template<class T> void outv(T v){rep(i,v.size()){if(i)cout<<' ';cout<<v[i];}cout<<'\n';}
template<class T> void outvv(T v){rep(i,v.size())outv(v[i]);}
template<class T> bool isin(T x,T l,T r){return (l)<=(x)&&(x)<=(r);}
template<class T> void yesno(T b){if(b)out("yes");else out("no");}
template<class T> void YesNo(T b){if(b)out("Yes");else out("No");}
template<class T> void YESNO(T b){if(b)out("YES");else out("NO");}
template<class T> void outset(T s){auto itr=s.begin();while(itr!=s.end()){if(itr!=s.begin())cout<<' ';cout<<*itr;itr++;}cout<<'\n';}
void outs(ll a,ll b){if(a>=inf-100)out(b);else out(a);}
ll gcd(ll a,ll b){if(b==0)return a;return gcd(b,a%b);}
ll modpow(ll a,ll b){ll res=1;a%=mod;while(b){if(b&1)res=res*a%mod;a=a*a%mod;b>>=1;}return res;}

int main(){
    ll n,m;cin>>n>>m;
    vi v(n);rep(i,n)cin>>v[i];
    vvp g(n);
    rep(i,m){
        ll a,b;cin>>a>>b;a--;b--;
        g[a].pb(b,i);g[b].pb(a,i);
    }
    vi lk(n),dep(n,-1);
    vb is_bridge(m,false);
    function<void(ll,ll,ll)> dfs=[&](ll i,ll p,ll e){
        lk[i]=dep[i];
        for(P x:g[i])if(x.fi!=p){
            if(dep[x.fi]==-1){
                dep[x.fi]=dep[i]+1;
                dfs(x.fi,i,x.se);
                chmin(lk[i],lk[x.fi]);
            }
            else chmin(lk[i],dep[x.fi]);
        }
        if(lk[i]==dep[i]&&i)is_bridge[e]=true;
    };
    dep[0]=0;dfs(0,-1,-1);
    vi gr(n,-1);
    ll num_gr=0;
    rep(i,n)if(gr[i]==-1){
        gr[i]=num_gr;
        queue<ll> que;que.push(i);
        while(!que.empty()){
            ll t=que.front();que.pop();
            for(auto x:g[t])if(!is_bridge[x.se]){
                if(gr[x.fi]==-1){
                    gr[x.fi]=num_gr;que.push(x.fi);
                }
            }
        }
        num_gr++;
    }
    vvi G(num_gr);
    rep(i,n)for(auto x:g[i])if(is_bridge[x.se])G[gr[i]].pb(gr[x.fi]);
    vi val(num_gr);
    rep(i,n)val[gr[i]]+=v[i];
    vi dp(num_gr);
    ll ans=0;
    function<void(ll,ll)> dfs2=[&](ll i,ll p){
        vi al;
        for(ll x:G[i])if(x!=p){
            dfs2(x,i);
            al.pb(dp[x]);
        }
        rsort(al);
        if(al.size())chmax(ans,al[0]+val[i]);
        if(al.size()>1)chmax(ans,al[0]+al[1]+val[i]);
        dp[i]=val[i];if(al.size())dp[i]+=al[0];
    };dfs2(0,-1);
    out(ans);
}
accuracy: 0.9642857142857143
time_ms: 60
memory_kb: 31120
final_rank: 20

code_snippet: #include <bits/stdc++.h>

using namespace std;

template <class Func>
class FixPoint : Func {
public:
    explicit constexpr FixPoint(Func&& f) noexcept : Func(forward<Func>(f)) {}

    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return Func::operator()(*this, std::forward<Args>(args)...);
    }
};

template <class Func>
static inline constexpr decltype(auto) makeFixPoint(Func&& f) noexcept {
    return FixPoint<Func>{forward<Func>(f)};
}

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    int n, m;
    cin >> n >> m;

    vector<int> v(n);
    vector<vector<int> > g(n);

    for (int i = 0; i < n; ++i) {
        cin >> v[i];
    }

    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        --u, --v;
        g[u].emplace_back(v);
        g[v].emplace_back(u);
    }

    vector<int> depth(n, -1), imos(n);

    makeFixPoint([&](auto rec, int cur, int pre, int dep) -> void {
        if (depth[cur] == -1) {
            depth[cur] = dep;
        } else {
            if (depth[pre] > depth[cur]) {
                imos[pre]++;
                imos[cur]--;
            } else {
                imos[cur]++;
                imos[pre]--;
            }
            return;
        }
        for (auto &to : g[cur]) {
            if (to != pre) rec(to, cur, dep + 1);
        }
    }) (0, -1, 0);

    vector<bool> visited(n);

    makeFixPoint([&](auto rec, int cur) -> int {
        visited[cur] = true;
        for (auto &to : g[cur]) {
            if (!visited[to]) imos[cur] += rec(to);
        }
        return (imos[cur]);
    }) (0);

    vector<int> comp(n, -1);
    int ptr = 0;

    for (int i = 0; i < n; ++i) {
        if (comp[i] == -1) {
            makeFixPoint([&](auto dfs, int cur, int cnt) -> void {
                if (comp[cur] != -1) return;
                comp[cur] = cnt;
                for (auto &to : g[cur]) {
                    int u = cur, v = to;
                    if (depth[u] > depth[v]) swap(u, v);
                    if (imos[v] > 0) dfs(to, cnt);
                }
            }) (i, ptr);
            ++ptr;
        }
    }

    vector<vector<int> > tree(ptr);
    vector<int> sum(ptr);

    for (int i = 0; i < n; ++i) {
        sum[comp[i]] += v[i];
        for (auto &to : g[i]) {
            int u = i, v = to;
            if (depth[u] > depth[v]) swap(u, v);
            if (imos[v] == 0) {
                tree[comp[i]].emplace_back(comp[to]);
            }
        }
    }

    vector<int> dist(ptr);
    auto tree_d = makeFixPoint([&](auto rec, int cur, int par) -> void {
        static int d_sum = 0;
        d_sum += sum[cur];
        dist[cur] = d_sum;
        for (auto &to : tree[cur]) {
            if (to != par) rec(to, cur);
        }
        d_sum -= sum[cur];
    });

    tree_d(0, -1);
    int s = max_element(begin(dist), end(dist)) - dist.begin();
    tree_d(s, -1);

    cout << *max_element(begin(dist), end(dist)) << '\n';

    return (0);
}
accuracy: 1
time_ms: 20
memory_kb: 25508
final_rank: 2

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#include <ext/rope>
 
using namespace std;
  
#define rep(i,n) for(int i=0;i<(n);++i)
#define reps(i,n) for(int i=1;i<=(n);++i)
#define all(x) begin(x),end(x)
#define Fixed fixed << setprecision(12)
#define int int_fast64_t
using pii = pair<int,int>;
constexpr int32_t INF  = 0x3f3f3f3f;
constexpr int_fast64_t LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int mod1 = 1e9+7;
constexpr int mod2 = 998244353;
  
template <class Func>
class FixPoint : Func {
public:
    explicit constexpr FixPoint(Func&& f) noexcept : Func(forward<Func>(f)) {}
  
    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return Func::operator()(*this, std::forward<Args>(args)...);
    }
};
  
template <class Func>
static inline constexpr decltype(auto) makeFixPoint(Func&& f) noexcept {
    return FixPoint<Func>{forward<Func>(f)};
}

template<class T, class U> istream& operator>>(istream& is, pair<T, U>& p){ is >> p.first >> p.second; return (is); }
template<class T, class U> ostream& operator<<(ostream& os, pair<T, U>& p){ os << p.first << ' ' << p.second; return (os); }
  
template <class A, class B> inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }
template <class A, class B> inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }
  
template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T,vector<T>,greater<T> >;
template <class A, class B> using umap = unordered_map<A,B>;
  
template <class T> using Max_Heap = __gnu_pbds::priority_queue<T, less<T>, __gnu_pbds::rc_binomial_heap_tag>;
template <class T> using Min_Heap = __gnu_pbds::priority_queue<T, greater<T>, __gnu_pbds::rc_binomial_heap_tag>;
template <class T> using Set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
template <class K, class V> using Umap = __gnu_pbds::gp_hash_table<K, V>;
template <class T> using Rope = __gnu_cxx::rope<T>;
using Trie = __gnu_pbds::trie<string, __gnu_pbds::null_type, __gnu_pbds::trie_string_access_traits<>, __gnu_pbds::pat_trie_tag, __gnu_pbds::trie_prefix_search_node_update>;
  
inline int square(int a){ return a * a;}
inline int updiv(int a,int b){ return (a + b - 1) / b; }

constexpr int dx[] = {1,0,-1,0,1,1,-1,-1};
constexpr int dy[] = {0,-1,0,1,1,-1,-1,1};

struct UnionFind{
    int n;
    vector<int> data;

    UnionFind(int sz) : n(sz), data(sz, -1){}

    bool unite(int x, int y){
        x = find(x), y = find(y);
        if(x == y) return (false);
        if(data[x] > data[y]) swap(x, y);
        data[x] += data[y];
        data[y] = x;
        return (true);
    }

    int find(int k){
        if(data[k] < 0) return (k);
        return (data[k] = find(data[k]));
    }

    int size(int k){
        return (-data[find(k)]);
    }

    bool same(int x, int y){
        return (find(x) == find(y));
    }

    vector<vector<int> > groups(){
        vector<int> leader_buf(n), group_size(n);
        for(int i = 0; i < n; ++i){
            leader_buf[i] = find(i);
            group_size[leader_buf[i]]++;
        }
        vector<vector<int> > res(n);
        for(int i = 0; i < n; ++i){
            res[i].reserve(group_size[i]);
        }
        for(int i = 0; i < n; ++i){
            res[leader_buf[i]].emplace_back(i);
        }
        res.erase(
            remove_if(res.begin(), res.end(),
                      [&](const vector<int>& v){ return (v.empty()); }),
            res.end());
        return (res);
    }
};

signed main(){
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout.setf(ios_base::fixed);
    cout.precision(10);

    int n, m;
    cin >> n >> m;

    vector<int> v(n);

    for(int i = 0; i < n; ++i){
        cin >> v[i];
    }

    vector<vector<int> > g(n);

    vector<int> s(m), t(m);
    for(int i = 0; i < m; ++i){
        cin >> s[i] >> t[i];
        --s[i], --t[i];
        g[s[i]].emplace_back(t[i]);
        g[t[i]].emplace_back(s[i]);
    }

    vector<pair<int, int> > low_link;
    vector<int> depth(n, -1);
    makeFixPoint([&](auto rec, int now, int pre, int dep) -> void{
        if(depth[now] == -1){
            depth[now] = dep;
        }else{
            if(depth[pre] > depth[now]){
                low_link.emplace_back(pre, now);
            }else{
                low_link.emplace_back(now, pre);
            }
            return;
        }
        for(auto e: g[now]){
            if(e != pre){
                rec(e, now, dep + 1);
            }    
        }
        return;
    })(0, -1, 0);

    sort(all(low_link));
    low_link.erase(unique(all(low_link)), low_link.end());

    vector<int> imos(n);
    for(auto [r, l] : low_link){
        imos[r]++;
        imos[l]--;
    } 

    vector<bool> visited(n);
    makeFixPoint([&](auto rec, int now) -> int{
        visited[now] = true;
        for(auto e: g[now]){
            if(!visited[e]){
                imos[now] += rec(e);
            }
        }
        return (imos[now]);
    })(0);

    UnionFind uf(n);

    vector<pair<int, int> > bli;
    for(int i = 0; i < m; ++i){
        if(depth[s[i]] > depth[t[i]]){
            swap(s[i], t[i]);
        }
        if(imos[t[i]]){
            uf.unite(s[i], t[i]);
        }else{
            bli.emplace_back(s[i], t[i]);
        }
    }

    vector<int> node;
    for(int i = 0; i < n; ++i){
        node.emplace_back(uf.find(i));
    }

    sort(all(node));
    node.erase(unique(all(node)), node.end());

    int siz = node.size();
    vector<int> pos(n);

    for(int i = 0; i < siz; ++i){
        pos[node[i]] = i;
    }

    vector<int> sum(siz);
    for(int i = 0; i < n; ++i){
        sum[pos[uf.find(i)]] += v[i]; 
    }

    vector<vector<int> > tree(siz);

    for(auto [a, b] : bli){
        a = pos[uf.find(a)];
        b = pos[uf.find(b)];
        tree[a].emplace_back(b);
        tree[b].emplace_back(a);
    }

    auto getcost = makeFixPoint([&](auto getcost, vector<int> &cost, int now, int pre) -> void{
        static int ssuumm = 0;
        ssuumm += sum[now];
        cost[now] = ssuumm;
        for(auto e: tree[now]){
            if(e != pre){
                getcost(cost, e, now);
            }
        }
        ssuumm -= sum[now];
        return;
    });

    vector<int> cost(siz);
    getcost(cost, 0, -1);
    int x = max_element(all(cost)) - cost.begin();
    getcost(cost, x, -1);

    cout << *max_element(all(cost)) << '\n';

    return (0);
}
accuracy: 1
time_ms: 30
memory_kb: 34416
final_rank: 7

code_snippet: #include <bits/stdc++.h>

using namespace std;

using int64 = long long;
// const int mod = 1e9 + 7;
const int mod = 998244353;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


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 != v.size() ? " " : "");
  }
  return os;
}

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

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

template< typename T = int >
struct Edge {
  int from, to;
  T cost;
  int idx;

  Edge() = default;

  Edge(int from, int to, T cost = 1, int idx = -1) : from(from), to(to), cost(cost), idx(idx) {}

  operator int() const { return to; }
};

template< typename T = int >
struct Graph {
  vector< vector< Edge< T > > > g;
  int es;

  Graph() = default;

  explicit Graph(int n) : g(n), es(0) {}

  size_t size() const {
    return g.size();
  }

  void add_directed_edge(int from, int to, T cost = 1) {
    g[from].emplace_back(from, to, cost, es++);
  }

  void add_edge(int from, int to, T cost = 1) {
    g[from].emplace_back(from, to, cost, es);
    g[to].emplace_back(to, from, cost, es++);
  }

  void read(int M, int padding = -1, bool weighted = false, bool directed = false) {
    for(int i = 0; i < M; i++) {
      int a, b;
      cin >> a >> b;
      a += padding;
      b += padding;
      T c = T(1);
      if(weighted) cin >> c;
      if(directed) add_directed_edge(a, b, c);
      else add_edge(a, b, c);
    }
  }
};

template< typename T = int >
using Edges = vector< Edge< T > >;

/**
 * @brief Low-Link(橋/関節点)
 * @see http://kagamiz.hatenablog.com/entry/2013/10/05/005213
 * @docs docs/low-link.md
 */
template< typename T = int >
struct LowLink : Graph< T > {
public:
  using Graph< T >::Graph;
  vector< int > ord, low, articulation;
  vector< Edge< T > > bridge;
  using Graph< T >::g;

  virtual void build() {
    used.assign(g.size(), 0);
    ord.assign(g.size(), 0);
    low.assign(g.size(), 0);
    int k = 0;
    for(int i = 0; i < (int) g.size(); i++) {
      if(!used[i]) k = dfs(i, k, -1);
    }
  }

  explicit LowLink(const Graph< T > &g) : Graph< T >(g) {}

private:
  vector< int > used;

  int dfs(int idx, int k, int par) {
    used[idx] = true;
    ord[idx] = k++;
    low[idx] = ord[idx];
    bool is_articulation = false, beet = false;
    int cnt = 0;
    for(auto &to : g[idx]) {
      if(to == par && !exchange(beet, true)) {
        continue;
      }
      if(!used[to]) {
        ++cnt;
        k = dfs(to, k, idx);
        low[idx] = min(low[idx], low[to]);
        is_articulation |= par >= 0 && low[to] >= ord[idx];
        if(ord[idx] < low[to]) bridge.emplace_back(to);
      } else {
        low[idx] = min(low[idx], ord[to]);
      }
    }
    is_articulation |= par == -1 && cnt > 1;
    if(is_articulation) articulation.push_back(idx);
    return k;
  }
};

/**
 * @brief Two-Edge-Connected-Components(二重辺連結成分分解)
 * @docs docs/two-edge-connected-components.md
 */
template< typename T = int >
struct TwoEdgeConnectedComponents : LowLink< T > {
public:
  using LowLink< T >::LowLink;
  using LowLink< T >::g;
  using LowLink< T >::ord;
  using LowLink< T >::low;
  using LowLink< T >::bridge;

  vector< int > comp;
  Graph< T > tree;
  vector< vector< int > > group;

  int operator[](const int &k) const {
    return comp[k];
  }

  void build() override {
    LowLink< T >::build();
    comp.assign(g.size(), -1);
    int k = 0;
    for(int i = 0; i < (int) comp.size(); i++) {
      if(comp[i] == -1) dfs(i, -1, k);
    }
    group.resize(k);
    for(int i = 0; i < (int) g.size(); i++) {
      group[comp[i]].emplace_back(i);
    }
    tree = Graph< T >(k);
    for(auto &e : bridge) {
      tree.add_edge(comp[e.from], comp[e.to], e.cost);
    }
  }

  explicit TwoEdgeConnectedComponents(const Graph< T > &g) : Graph< T >(g) {}

private:
  void dfs(int idx, int par, int &k) {
    if(par >= 0 && ord[par] >= low[idx]) comp[idx] = comp[par];
    else comp[idx] = k++;
    for(auto &to : g[idx]) {
      if(comp[to] == -1) dfs(to, idx, k);
    }
  }
};

template< typename sum_t, typename key_t >
struct ReRooting {
  struct Edge {
    int to;
    key_t data;
    sum_t dp, ndp;
  };

  using F = function< sum_t(sum_t, sum_t) >;
  using G = function< sum_t(sum_t, key_t) >;

  vector< vector< Edge > > g;
  vector< sum_t > subdp, dp;
  const sum_t ident;
  const F f;
  const G gg;

  ReRooting(int V, const F f, const G g, const sum_t &ident)
      : g(V), f(f), gg(g), ident(ident), subdp(V, ident), dp(V, ident) {}

  void add_edge(int u, int v, const key_t &d) {
    g[u].emplace_back((Edge) {v, d, ident, ident});
    g[v].emplace_back((Edge) {u, d, ident, ident});
  }

  void add_edge_bi(int u, int v, const key_t &d, const key_t &e) {
    g[u].emplace_back((Edge) {v, d, ident, ident});
    g[v].emplace_back((Edge) {u, e, ident, ident});
  }

  void dfs_sub(int idx, int par) {
    for(auto &e : g[idx]) {
      if(e.to == par) continue;
      dfs_sub(e.to, idx);
      subdp[idx] = f(subdp[idx], gg(subdp[e.to], e.data));
    }
  }

  void dfs_all(int idx, int par, const sum_t &top) {
    sum_t buff{ident};
    for(int i = 0; i < (int) g[idx].size(); i++) {
      auto &e = g[idx][i];
      e.ndp = buff;
      e.dp = gg(par == e.to ? top : subdp[e.to], e.data);
      buff = f(buff, e.dp);
    }
    dp[idx] = buff;
    buff = ident;
    for(int i = (int) g[idx].size() - 1; i >= 0; i--) {
      auto &e = g[idx][i];
      if(e.to != par) dfs_all(e.to, idx, f(e.ndp, buff));
      e.ndp = f(e.ndp, buff);
      buff = f(buff, e.dp);
    }
  }

  vector< sum_t > build() {
    dfs_sub(0, -1);
    dfs_all(0, -1, ident);
    return dp;
  }
};

int main() {
  int N, M;
  cin >> N >> M;
  vector< int > V(N);
  cin >> V;
  TwoEdgeConnectedComponents<> g(N);
  g.read(M);
  g.build();
  auto &t = g.tree;
  vector< int > sum(t.size());
  for(int i = 0; i < t.size(); i++) {
    for(auto &j : g.group[i]) sum[i] += V[j];
  }
  auto f1 = [](int a, int b) {
    return max(a, b);
  };
  auto f2 = [](int a, int b) {
    return a + b;
  };
  ReRooting< int, int > dp(t.size(), f1, f2, 0);
  for(int i = 0; i < t.size(); i++) {
    for(auto &j : t.g[i]) {
      if(i < j) {
        dp.add_edge_bi(i, j, sum[j], sum[i]);
      }
    }
  }
  auto ret = dp.build();
  for(int i = 0; i < ret.size(); i++) ret[i] += sum[i];
  cout << *max_element(begin(ret), end(ret)) << "\n";
}
accuracy: 1
time_ms: 50
memory_kb: 44688
final_rank: 18

code_snippet: #line 1 "a.cpp"
#include<iostream>
#include<algorithm>
using namespace std;
#line 1 "/home/kotatsugame/library/graph/TECC.cpp"
//Two Edge Connected Components require bridge
#line 1 "/home/kotatsugame/library/graph/bridge.cpp"
#include<vector>
#line 3 "/home/kotatsugame/library/graph/bridge.cpp"
struct bridge{
	int n;
	vector<int>ord,low;
	vector<bool>art;
	vector<vector<int> >G;
	bridge(int n_=0):n(n_),ord(n_,-1),low(n_),art(n_,false),G(n_){}
	void add_edge(int u,int v)
	{
		G[u].push_back(v);
		G[v].push_back(u);
	}
	bool operator[](int i)const{return art[i];}
	bool is_bridge(int a,int b)const
	{
		if(ord[a]>ord[b])swap(a,b);
		return ord[a]<low[b];
	}
	void dfs(int u,int p,int&k)
	{
		low[u]=ord[u]=k++;
		bool now=false;
		int pc=0;
		for(int v:G[u])
		{
			if(ord[v]==-1)
			{
				dfs(v,u,k);
				low[u]=min(low[u],low[v]);
				now=now||ord[u]<=low[v];
			}
			else if(v!=p||pc++)
			{
				low[u]=min(low[u],ord[v]);
			}
		}
		art[u]=now;
	}
	void build()
	{
		int k=0;
		for(int u=0;u<n;u++)if(ord[u]==-1)
		{
			int cnt=0;
			low[u]=ord[u]=k++;
			for(int v:G[u])if(ord[v]==-1)
			{
				dfs(v,u,k);
				cnt++;
			}
			if(cnt>=2)art[u]=true;
		}
	}
};
#line 3 "/home/kotatsugame/library/graph/TECC.cpp"
struct TECC:bridge{
	vector<int>comp;
	TECC(int n_=0):bridge(n_),comp(n_,-1){}
	int operator[](int i)const{return comp[i];}
	void dfs(int u,int p,int&k)
	{
		comp[u]=p==-1||is_bridge(p,u)?k++:comp[p];
		for(int v:G[u])if(comp[v]==-1)dfs(v,u,k);
	}
	int build()
	{
		bridge::build();
		int k=0;
		for(int u=0;u<n;u++)if(comp[u]==-1)dfs(u,-1,k);
		return k;
	}
	int build(vector<vector<int> >&H)
	{
		int k=build();
		H.assign(k,vector<int>());
		for(int u=0;u<n;u++)
		{
			for(int v:G[u])if(comp[u]!=comp[v])
			{
				H[comp[u]].push_back(comp[v]);
			}
		}
		return k;
	}
};
#line 5 "a.cpp"
int N,M,K;
int v[1<<17];
int V[1<<17];
vector<vector<int> >H;
int ans;
int dfs(int u,int p)
{
	int mx1=0,mx2=0;
	for(int v:H[u])if(v!=p)
	{
		int d=dfs(v,u);
		if(mx1<d)
		{
			mx2=mx1;
			mx1=d;
		}
		else if(mx2<d)mx2=d;
	}
	ans=max(ans,mx1+mx2+V[u]);
	return mx1+V[u];
}
main()
{
	cin>>N>>M;
	for(int i=0;i<N;i++)cin>>v[i];
	TECC P(N);
	for(int i=0;i<M;i++)
	{
		int a,b;cin>>a>>b;
		P.add_edge(a-1,b-1);
	}
	K=P.build(H);
	for(int i=0;i<N;i++)V[P[i]]+=v[i];
	dfs(0,-1);
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 70
memory_kb: 23388
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

class TwoEdgeConnectedComponents {
    void dfs(int i, int &pos){
        ord[i] = low[i] = pos++;
        int mul = 0;
        for (auto &&j : G[i]) {
            if(j == par[i] && !mul){
                mul = 1;
                continue;
            }
            if(~ord[j]){
                low[i] = min(low[i], ord[j]);
                continue;
            }
            par[j] = i;
            dfs(j, pos);
            size[i] += size[j];
            low[i] = min(low[i], low[j]);
        }
    }

    void dfs2(int i){
        out[bridge[i]].emplace_back(i);
        for (auto &&j : G[i]) {
            if(~bridge[j] || is_bridge(i, j)) continue;
            bridge[j] = bridge[i];
            dfs2(j);
        }
    }
public:
    vector<int> ord, low, par, bridge, size;
    vector<vector<int>> G, out;
    explicit TwoEdgeConnectedComponents(int n): ord(n, -1), low(n), par(n, -1), bridge(n, -1), size(n, 1), G(n){}

    inline bool is_bridge(int i, int j){
        if(ord[i] > ord[j]) swap(i, j);
        return ord[i] < low[j];
    }

    void add_edge(int u, int v){
        if(u != v){
            G[u].emplace_back(v);
            G[v].emplace_back(u);
        }
    }

    int build(){
        int n = G.size(), pos = 0;
        for (int i = 0; i < n; ++i) {
            if(ord[i] < 0) dfs(i, pos);
        }
        int k = 0;
        for (int i = 0; i < n; ++i) {
            if(!~bridge[i]){
                bridge[i] = k++;
                out.emplace_back();
                dfs2(i);
            }
        }
        return k;
    }
};



int main() {
    int n, m;
    cin >> n >> m;
    vector<int> V(n);
    for (auto &&i : V) scanf("%d", &i);
    TwoEdgeConnectedComponents G_(n);
    for (int i = 0; i < m; ++i) {
        int u, v;
        scanf("%d %d", &u, &v);
        u--; v--;
        G_.add_edge(u, v);
    }
    int k = G_.build();
    vector<vector<int>> G(k);
    vector<ll> v(k);
    for (int i = 0; i < k; ++i) {
        for (auto &&j : G_.out[i]) {
            v[i] += V[j];
        }
    }
    for (int i = 0; i < n; ++i) {
        for (auto &&j : G_.G[i]) {
            if(G_.is_bridge(i, j)){
                G[G_.bridge[i]].emplace_back(G_.bridge[j]);
            }
        }
    }
    ll ans = 0;
    auto dfs = [&](int x, int par, auto &&f) -> void {
        ll val1 = 0, val2 = 0;
        for (auto &&i : G[x]) {
            if(i == par) continue;
            f(i, x, f);
            if(val1 <= v[i]){
                val2 = val1; val1 = v[i];
            }else if(val2 <= v[i]){
                val2 = v[i];
            }
        }
        ans = max(ans, val1+val2+v[x]);
        v[x] += val1;
    };
    dfs(0, -1, dfs);
    cout << ans << "\n";
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 27300
final_rank: 3